Оформление кода

    Данным топиком я хочу поднять вопрос о качестве кода, независимо от используемого языка программирования. В топике я приведу пару советов и методик, которых придерживаются у нас в компании. Я не буду утверждать, что они являются верными, ведь у каждого есть свой вкус и свои предпочтения. Но все равно, в каждом кругу разработчиков, работающих вместе, существуют какие либо правила оформления кода.
    Так же, не мало важно увидеть в комментариях ваши подходы и «любимый стиль».


    Большинство советов в топике — вырезки из книги Макконнелла «Совершенный код» (Steve McConnell — «Code Complete»).

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

    Правило Ноль: строго следуйте code style «гайдам», принятым в вашей корпоративной среде.

    Качественные методы


    Метод должен служить одной четко определенной цели

    Эта цель должна быть полностью отражена в его имени: получить текущего пользователя — getСurrentUser(). Размытое, неоднозначное и откровенно плохое имя метода чаще всего является
    главным свидетельством его неудачной реализации.

    Примеры хороших имен методов:
    Customer::getFullName() – получить полное имя клиента UserMapper::createAndGetUser(userId) – исключение, в контексте User-маппера побочная роль метода (вернуть вновь созданный user-объект) достаточно очевидна.

    MonthRevenue.calculate(), MonthRevenue.export() – неинформативные сами по себе имена методов оказываются полностью достаточными в контексте ООП вызовов этих методов «на себя» (другими словами, метод призван совершить действие над вызвавшим его объектом и его данными).


    Примеры плохих имен методов:
    computeMonthRevenueAndDoExport() – несколько несвязанных целей
    processInput(), handleCalculation() – невыразительность, размытость цели
    метода

    • Следует использовать парные антонимы для методов, выполняющих парные (противоположные) действия: open/close, show/hide, add/remove, insert/delete.
    • Метод должен быть отформатирован в строгом соответствии с принятыми конвенциями, «код стайлами» и так далее.
    • Метод должен быть документирован (как сам интерфейс метода, так и комментарии к важным и сложным участкам).
    • Метод не должен изменять глобальные переменные.
    • Метод не должен иметь слишком большое количество параметров (не более 7).
    • Параметры следует упорядочивать по степени их важности либо порядку их использования внутри метода:
      setMonthExchangeRate(month, exchangeRate)
      getCustomerMonthRevenue(customerId, month)

    • Неизменяемые параметры не должны передаваться по ссылке.
    • Не должно быть неиспользуемых «брошенных» переменных и параметров.
    • Не используйте входные параметры в качестве рабочих переменных.
    • Метод должен быть защищен от плохих данных, которые могут нарушить его работу.
      monthRevenue = fixedValue * 0.6 / inputParam

    • Метод не должен быть слишком большим (не более 100 строк).

    Качественные переменные

    Переменная должна полно описывать представляемую сущность

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

    Умеренная длина

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

    Спецификаторы

    В именах переменных следует использовать спецификаторы Count и Index вместо Num. Это логично, так как они четко отражают назначение переменной (количество и номер), а вот Num выглядит достаточно двусмысленно и может в некоторых случаях ввести в заблуждение.

    Индексы циклов

    Это нормально, когда небольшой цикл из 1-3 строк имеет индекс под названием I,j или k. Но если тело цикла заметно больше, то лучше давать индексам осмысленные имена. И вам будет проще разобраться с таким кодом со временем (сразу же становится понятно, что делает цикл) и другим программистам, которые будут работать с вашим кодом, тоже станет легче.

    Префиксы при перечислениях

    При использовании перечислений имеет смысл ставить префикс. Например, в случае таких переменных STATUS_OPENED, STATUS_TO_CONFIRM, STATUS_CONFIRMED перечисление идет с префиксом STATUS_.

    Константы

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

    Конвенции

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

    Меньше обобщенности

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

    Примеры хороших имен переменных:

    employeesCount, userMonthWorkDaysCount, yearTax, maxComputedSalary


    Примеры плохих имен переменных:

    x, $fb, f_ar_type_data, f_obj_result, inputData, returnValue, resultArray, obj1, obj2


    • Хорошее правило — давать более короткие имена переменным с более узкой областью видимости, соответственно, более длинные и подробные имена — переменным с более глобальной (в рамках метода) областью видимости.
    • Для переменных-счетчиков коротких циклов допускаются традиционные односимвольные имена — i, j, k, …. Если переменная будет использоваться вне цикла, ее имя должно быть более выразительным и понятным:

      teamScoresCount = 0;
      teamScores = array();
      
      while (teamScoresIterator.nextScore())
      {
      	teamScores[teamScoresCount++] =
      	teamScoresIterator.getCurrentScore();
      }
      
      foreach ($teamScores as $teamScoreIndex => $teamScoreValue)
      	foreach ($aTeamScores as $iTeamScoreIndex => $iTeamScore)
      	{
      		// over 9000 lines of code
      	}
      		

    • Избегать аббревиатур и неочевидных сокращений. Плохо: cl (call stack), gfx (graphics), dpt (department).
    • Использовать только согласованные сокращения: только max либо только maximum; только num либо только no; месяцы либо по первым трем буквам (Jan, Feb, Mar) либо полностью.
    • Избегать имен с похожими значениями (в рамках конкретной области видимости): fileNumber/fileIndex; scoresNumber/scoresCount. Применять только один из вариантов. Пишите имена без орфографических ошибок и опечаток
    • Избегайте именования переменных ничего не значащими (значащими только для вас) именами (snuffi, elizabeth) если только они не являются представляемыми в программе сущностями.
    • Имена булевых переменных должны быть в утвердительной форме и подразумевать булево значение: done, error, found, finished. Плохо: status, source.
    • Минимизация области видимости переменной:

      • Располагать команды использующие одну и туже переменную как можно
        ближе друг к другу.
      • Инициализировать переменные непосредственно перед их использованием

    • Использовать каждую переменную только с одной целью.

    • Инициализировать переменные значением по умолчанию.



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

    Согласитесь, читать такой код:
    function()
    {
    	$a = 1;
    	$b = 2;
    	$c = 3;
    	$sql = '
    		SELECT
    			*
    		FROM
    			tbl
    		WHERE
    			a = 1';
    }
    


    Более приятно, чем

    function(){
      $a = 1;
     $b = 2; $c = 3;
    
     $sql = 'SELECT	* FROM tbl
    WHERE a = 1';
    }
    


    Ссылка на книгу Code Complete.
    Спасибо за внимание.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 109

    • UFO just landed and posted this here
        +2
        "_" не исключение, для приватных полей следует использовать this.variable синтаксис.
          0
          это неправда. Во-первых, не путайте официальный гайдлайн с правилами хорошего тона. Устоявшихся традиций даже не две, а скорее три: с this, с underscore (_) и c m_. Последняя менее распространена, но ею, например, пользуется Рихтер.
          Во-вторых, даже в официальном гайдлайне ничего не сказано о правилах именования приавтных полей. Пруф: msdn.microsoft.com/en-us/library/ms229012.aspx The naming guidelines for fields apply to static public and protected fields. You should not define public or protected instance fields.
            0
            SA1309: FieldNamesMustNotBeginWithUnderscore.
            By default, StyleCop disallows the use of underscores, m_, etc., to mark local class fields, in favor of the ‘this.’ prefix.

            Официальный гайдлайн не все читают, справедливости ради StyleCop тоже не все используют. Раньше сам писал m_, потом _, потом this. В Microsoft так-то бардак в исходных кодах привычное дело, так что проще положиться на инструмент который проверит и подскажет, чем на бумажный гайдлайн.
          +2
          Угу, и имена методов с большой буквы в C#. Для и для имен булевых переменных, лично мне нравятся вопросительные предложения. Т.е. имя переменной не «done», а «isDone». Как то логичнее выглядит.
            –1
            job.isDone — вопросительное предложение?
              +1
              Во-первых, я говорил про переменные, а вы привели пример свойства/поля.
              Во-вторых, да я считаю, что при чтении
              if (job.IsDone)
              лучше, чем
              if (job.Done)
              В-третьих, каждая команда вырабатывает свои соглашения, если вам больше нравится без Is, то это ваше право, просто надо всем придерживаться этого стиля и все…
                0
                В некоторых языках используется название именно «переменные объекта/класса», свойств/полей там нет. Но вообще я спросил, имея в виду, что в случае имени переменной/свойства/поля, то есть jobIsDone или job.isDone.isDone (сам такую форму предпочитаю) это утверждение, подразумевающее наличии какого-то объекта (не в смысле ООП, а в смысле существительного) могущее быть ложным или истинным, но не вопрос.
                0
                Немного в офтопик уйду: нравится, как это в ruby сделано, прямо в названии метода знак вопроса, исключительно хорошо.
                  0
                  и тут же замечу, что однозначно фигово в Ruby то, что это касается только методов-геттеров.

                  1.9.3-p194 :001 > @done? = false
                  SyntaxError: (irb):1: syntax error, unexpected '='
                  @done? = false
                  ^
                  from /usr/local/rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `'
              +2
              Бесит "_" у приватных полей в C#.
              +1
              Не знаю как можно не следовать общему стилю. Если пишешь как-то по другому, то твой код выглядит как белая ворона, что лично меня до жути бесит… все должно быть красиво, перфекциониз (кажется это так называется).
                +2
                Не знаю как можно не следовать общему стилю
                Очень просто.
                Когда проект большой, нужно сделать что-то небольшое, а времени знакомиться со всеми гайдлайнами проекта нет, то… вполне можно ляпнуть getJuneStat вместсо принятого getJunStat, при чем если рядом нет кода в котором написано getJunStat, то Вы просто не заметите, что Вы белая ворона:)

                  +1
                  Вы говорите верно, но иногда встречается код, из-за которого готов бросить программирование :)
                  А вообще, с книгой, ссылка на которую есть в конце топика, должен ознакомится каждый, особенно начинающий программист.
                    +2
                    ИМХО С этой книгой обязан познакомиться каждый не начинающий программист. По крайней мере 1 — 2 года опыта программирования должно быть, хотя бы для того, чтобы понимать что в ней написано.
                      +2
                      Угу, ознакомиться начинающему может быть просто вредно, если он начнёт следовать принципам не понимая зачем.
                  • UFO just landed and posted this here
                      +3
                      откровенно плохое имя метода чаще всего является главным свидетельством его неудачной реализации
                    +8
                    «obj1, obj2» как говориться — «нет худшей причины назвать переменную $c, чем та, что $a и $b уже заняты»
                      0
                      Ну на самом деле, многие так делают, и все правильно делают. Например, олимпиадное программирование, когда времени очень мало…
                        0
                        В олимпиадном программировании это не так критично на самом деле :) Много времени за компьютером тратится на обдумывание того — как писать, имена переменных по сравнению с этим тратят очень мало времени.
                        Ну и не стоит забывать, что IDE вполне сносно автодополняют имена переменных/методов/классов, а ими (IDE) на олимпиадах пользоваться не запрещено.
                          0
                          И, конечно же, не стоит забывать, что ваш код потом еще, возможно, придется читать сокоманднику, а он точно не обрадуется одно-двухсимвольным названиям переменных, если названия взяты наобум (w для ширины, h для высоты — логично, а вот «a» и «b» для того же — уже сложнее гораздо читать). В таком случае все сэкономленные секунды на написание коротких имен будут многократно съедены тем временем, которое ваш товарищ потратит на понимание кода — а вы ведь в это время, скорее всего, будете писать уже следующую задачу.
                            0
                            У всех есть скрипты, которые «просто должны работать и не важно что внутри», вот только внутри обычно такая жесть творится, что автор через месяц уже ничего не прочтет. Поэтому я обдумываю каждое название в коде — бывает долго, но иначе потом будет хуже.

                            А вообще, если вспомнить Дяду Боба, то в книге «Чистый код» он много и дотошно все моменты разбирает и объясняет что и почему.
                            0
                            Не критично, но юзают. А я и не говорил что время именно на кодирование уходит, пишут a, b, c, d… в том числе чтоб и не задумываться над названием. Ну и все-же кодируется так все быстрее, и аутокомплит тому не перечит.

                            Чтение сокомандником, происходит редко, и при наличии автора, который показывает и рассказывает.

                            Ну в общем, ваши аргументы, приняты частично). И как факт, таки многие так делают, и иногда все правильно делают.
                              +3
                              Ну и помимо олимпиадного, нормальный пример для a, b, c:

                              procedure swap(var a : integer, var b : integer);
                              var c : integer;
                              begin
                                   c := a;
                                   a := b;
                                   b := c;
                              end;

                              Что явно лучше чем FirstVariableForSwaping / swapVar1 / tempVar и кучи всего другого.
                                0
                                arg1, arg2, temp
                                  +1
                                  Мне кажется, что это не лучше чем a, b, c.

                                  arg1, arg2 — не информативно, и так понятно что процедура принимает первый аргумент, второй аргумент…

                                  temp — возможно и лучше, но если функция занимает 3 строки, и есть гарантия от самих небес что функция меняться не будет (как эта), то лучше не задумываться а писать что удобней.

                                  С другой стороны, конечно, хорошо всегда писать правильно, по меньшей мере чтоб привычку нарабатывать.
                                    0
                                    С a, b и c могут возникнуть ненужные ассоциации. Например две функции рядом triangle_square(a, b, c) и swap(a, b). Если первая понятна любому, изучавшему геометрию в школе (и английский :) ), то этого же любого вторая может заставить полезть в реализацию. чтобы посмотреть, а что же там со сторонами треугольника происходит, хотя никакого отношения ни к треугльнику, ни геометрии вообще она не имеет. Правда arg1 и arg2 неудачные названия, я бы взял var1 и var2, подчеркнув, что нужно указывать именно переменные, а не произвольные выражения.
                                      0
                                      Есть ещё вариант — назвать «left» и «right» или «first» и «second»
                                        0
                                        swap — основы основ, название как бы намекает, что там за аргументы).
                                        a, b, c — часто используются в высшей математике, алгебре и прочих весомых науках.
                                          0
                                          Вот и я про то, может возникнуть диссонанс между swap и её аргументами a и b. Вроде swap чисто техническое название, а a и b — научные.
                                            0
                                            Так хотелось найти пример, но боюсь что boost, .Net, Qt напилили что-то похожее на value1, value2 для таких функций((.

                                            a,b — все-же скорей инженерные, нежели научные. Наука кишит всякими тау, гамма… Впрочем и а, b к сожалению тоже.

                                            Ну ладно, буду делать как все, но аргумент в сторону сильных ассоциаций к a,b — не принимаю). Не верю в существование программистов, которые при виде swap(a, b) подумают про стороны треугольников.

                                            • UFO just landed and posted this here
                                          0
                                          Непонятно. Что такое «треугольный квадрат»? Я такого не только не знаю, но и представить себе не могу. Или имелось в виду TriangleArea?
                                            0
                                            Имелось, но словарь выдал на слово «площадь» перевод «square», а не «area». А представьте от меня ещё требуют комментарии иногда на английском писать :(
                            • UFO just landed and posted this here
                              +4
                              Всё же не все правила абсолютны.
                              Неизменяемые параметры не должны передаваться по ссылке.
                              Не используйте входные параметры в качестве рабочих переменных.
                              Метод должен быть защищен от плохих данных, которые могут нарушить его работу.

                              Если они большие, то можно и по ссылке. Пару мегабайт данных на фига пихать в функцию «напрямую»?
                              Если в функции 7 входных параметров, все из которых используются и сама функция небольшая, то переопределение может занять больше места/времени чем использование их как рабочих и привести след. разработчика в задумчивость.
                              Фактически это обязательно только в публичном методе. Приватный метод вполне имеет право полагаться на проверку этих данных перед ним. Иначе в цепочке вызовов может оказаться такой копипаст проверок, что жуть.
                                +1
                                Бывают еще и константные ссылки, которые как раз в большинстве случаев предпочтительны. И тогда их не удастся использовать как рабочие переменные.
                                +1
                                Спрашивал месяц назад по этому вопросу того самого Джона Кармака в Твиттере. Он же увлекается всяким таким. Кармак сказал, что по вопросам читабельности кода самое лучшее — вот это.
                                Ссылок на PDF на английском если что хватает, а лично мне книга понравилась, легко читается легко и сразу есть практическая польза. Code Complete безусловно шире по охвату тем и сравнивать их не стоит, но вдруг кто-то и эту книжку возьмет на вооружение.
                                  0
                                  Конкретизация методов/функций/переменных нужна только там, где код, с первого прочтения, может быть не очевиден. Не нужно комментировать, что вы делаете, комментируйте почему вы так делаете.
                                    +4
                                    Так же не мало важным является одинаковое оформление блоков кода, разбиение длинных условий на несколько строк и использование отступов.

                                    Согласитесь, читать такой код:
                                    Код красивый
                                    function()
                                    {
                                    $a = 1;
                                    $b = 2;
                                    $c = 3;
                                    $sql = '
                                    SELECT
                                    *
                                    FROM
                                    tbl
                                    WHERE
                                    a = 1';
                                    }

                                    Код компактный
                                    function(){
                                    $a = 1;
                                    $b = 2; $c = 3;

                                    $sql = 'SELECT * FROM tbl
                                    WHERE a = 1';
                                    }


                                    Более приятно, чем
                                    Приятно может быть и первый, но хорошим компромиссом для такой ситуации имхо было бы все-таки
                                    Код компромисный
                                    function(){
                                    $a = 1; $b = 2; $c = 3;
                                    $sql = 'SELECT * FROM tbl WHERE a = 1';
                                    }

                                    Потому что первый тип кода приводит к тому, что частенько приходится пролистывать страницы. Код должен быть разумно компактен. Особенно учитывая моду последних лет, когда 4:3 мониторы скукожили до 16:10, а потом и до 16:9… или вообще сумашедшие 21:9 habrahabr.ru/post/145276/
                                      +2
                                      Метод не должен быть слишком большим (не более 100)

                                      Не более чего? Строк/экранов/*байт/грамм? :)
                                        –1
                                        А разве не очевидно?
                                          –1
                                          Вам очевидно, мне очевидно, а тем, кому эта статья будет реально полезна, скорее всего может быть не очевидна.
                                            +1
                                            Знаете, если человек подумает про 100 экранов или 100 байт, ему лучше не продолжать программировать. Ему даже code complete не поможет. Всё таки у программистов должен быть мозг
                                              +3
                                              Да ладно. Вы реально весь такой правильный и никогда не делаете ошибок?
                                                +2
                                                При чем тут то делаю я ошибки или нет?
                                                Я просто уверен что большинство тут люди с хорошими мозгами, и однозначно поняли о какой еденице измерения шла речь.
                                                Метод размером 100 строк. Очевидно же.

                                                Какие к черту байты, экраны? Зачем вы бред несете? Вам приятно ощущать себя дурачком?

                                                Это серьёзный IT ресурс а не ясельная группа. Да, хабр сгавнивается с годами, все меньше серьёзных постов, но ведь это не повод устраивать смешнявочки из за недописок. Если вы нашли однозначную ошибку в статье — ну писните автору в ЛС. Зачем разводить детский сад?

                                                  +1
                                                  Инженерия и наука требуют точных высказываний, которые не дают шанса термину «неоднозначность».

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

                                                  Не принимайте близко к сердцу, практика показывает что в таких ситуациях дешевле будет сказать «Прошу прощения, поправил.»
                                                    0
                                                    Про очевидность я вам ответил выше.
                                                    Для вас очевидно (должно быть у вас есть мозг). Для меня очевидно (знаком с software metrics). A для кого-то начинающего может быть очевидно, что метод должен содержать не более 100 операций.

                                                    В итоге, не нравится мой комментарий — есть минус для него, есть минус в карму.
                                                    Выпустите пар на них и продолжайте читать сей серьёзный IT ресурс, вместо рассуждений на тему мозга у программистов.
                                                  +2
                                                  Конечно все догодались, но для этого пришлось напрячь мозг на 0.5 секунд. Ирония в том, что это в статье про перфикционизм и про прекрасно офрмленный, легко-читабельный код. Если бы эта надпись была в любой другой статье — никто бы и не обратил внимание.
                                                0
                                                Тут тоже всё очевидно:
                                                function(){
                                                  $a = 1;
                                                $b = 2; $c = 3; $sql = 'SELECT * FROM tbl
                                                WHERE a = 1'; return $this->my_sql->q($sql);
                                                }
                                                

                                                Что тут не очевидного?
                                                  0
                                                  Все очевидно. Только за такое форматирование кода хочется человека как минимум обозвать. Как минимум — редиской.
                                                    +3
                                                    "(не более 100)" — за это тоже.
                                                      –1
                                                      за троллинг — тоже. Я же исправил.
                                                    +1
                                                    Мне что-то не очевидно зачем там $a, $b, $c. И что такое метод q?
                                                      0
                                                      И как потом вызвать эту функцию? О чем пример?
                                                  +1
                                                  Спасибо, исправил
                                                  +5
                                                  Очень напоминает пересказ одной из глав «Совершенного кода»
                                                    +1
                                                    Ах, автор об этом упомянул. Я воспользовался правилом «The Wadsworth Constant» и сразу начал читать со второй трети статьи.
                                                    +1
                                                    Всё это круто и интересно, но опять таки в вакууме.
                                                    Возьмите любой открытый проект, найдите в нём код, который некрасивый/несовершенный, сделайте его красивым и выкладывайте на обсуждение.
                                                      –1
                                                      Если реч идет о PHP, то я всех, у себя в компании, пропогандирую PEAR coding standards.
                                                      В основном из-за того, что Drupal взял за базу эти правила и чуть-чуть изменил их под себя.
                                                      Drupal coding standards

                                                      А это, по моему скромному мнение уже слишком.
                                                      Код из статьи
                                                      function()
                                                      {
                                                          $a = 1;
                                                          $b = 2;
                                                          $c = 3;
                                                          $sql = '
                                                              SELECT
                                                                  *
                                                              FROM
                                                                  tbl
                                                              WHERE
                                                                  a = 1';
                                                      }
                                                      



                                                      Я бы писал так
                                                      function foo() {
                                                          $a = 1;
                                                          $b = 2;
                                                          $c = 3;
                                                      
                                                          $sql = 'SELECT *
                                                                    FROM tbl
                                                                  INNER JOIN tratata
                                                                    ON zozo.zozo = zaza
                                                                  WHERE 
                                                                   a = 1 OR
                                                                   z = 1000';
                                                      }
                                                      



                                                      Ну или как edogs в комментарии.
                                                        +1
                                                        оформление SQL кода, с новой строки (как у меня), или придерживаюсь всех отступов — как у вас, уже пожеланию. Главное что бы был читаем SQL (beautiful query). Различия незначительны, лишь в количестве действий при наборе — у вас отступов больше :)

                                                        а по поводу скобок и пустых строк — это, как описано в топике — строго по гайдлайнам компании.
                                                          0
                                                          Ничуть не слишком. Это удобно читать и камитить. Пример:
                                                          $sql = '
                                                          	SELECT
                                                          		  i.e_id
                                                          		, iv.iv_id		AS id
                                                          		, iv.value
                                                          		, iv.ep_id		AS element_property_id
                                                          	FROM
                                                          		' . $this->schema . '.item AS i
                                                          	LEFT JOIN
                                                          		' . $this->schema . '.item_value AS iv USING (i_id)
                                                          	WHERE
                                                          		i.i_id = '. $this->db->getSqlInt($item['id']) . '
                                                          ';
                                                          

                                                          Весь «скелет» запроса виден по SELECT...FROM...LEFT JOIN...WHERE. Из какой таблицы выборка, что выбираем, с чем джоиним, по каким условиям. Запятые в начале для камитов. Если завтра потребуется добавить новое поле, то в дифе мы увидим ", iv.new", т.е. затронута будет одна строка, а не две как в случае если поля разделять запятыми в конце строки.
                                                            +2
                                                            LEFT JOIN я бы сдвинул ещё, всё таки он относится к FROM, а не является самостоятельным элементом SELECT.

                                                            А вообще, когда выражение простое вроде «SELECT * FROM table», то при виде его разбитым на 4 строки возникает неоднозначная реакция.
                                                              0
                                                              В JOIN, как и в FROM, находится имя таблицы, поэтому он вровень с FROM. Ведь по сути, работаем мы уже не с таблицей указанной во FROM, а таблицей полученной объединением. Поэтому в SELECT у нас имена полей, а в FROM...JOIN таблица.

                                                              Какой бы простой код не использовался, он должен соответствовать стилю кодирования. Это сильно облегчает чтение кода, а бОльшую часть времени на живом проекте мы все же читаем, а не пишем код. Разбиение на несколько строк очень полезно оказывается для дифов. При однострочной записи изменение любой чисти запроса приводит к включению в диф камита всего запроса, разделенный же на строки запрос в дифе дает только измененные строки. Крайне полезно при командной разработке, особенно при отслеживании камитов других разработчиков. Но и работая в одиночку подход показывает себя очень удобным. Читаемость должна находится на первом месте. Многословность форматирования легко может фикситься через минификацию/обфускацию на этапе сборке проекта. В контексте php это сборка в phar файл(ы).
                                                                0
                                                                Ну я сматриваю (а иногда и пишу) FROM… JOIN… ON… как FROM (… JOIN… ON ...), то есть имея ввиду как раз, что «аргументом» FROM является как раз «виртуальная» таблица, а состоит она из одной или объединения двух или более — не суть. Ваш вариант мне напоминает запись типа
                                                                $var
                                                                =
                                                                  2
                                                                +
                                                                  2
                                                                

                                                                а я предпочитаю
                                                                $var
                                                                  =
                                                                    2
                                                                    +
                                                                    2
                                                                



                                                                  0
                                                                  Ну тут уж кому как удобно/какой стиль кодирования принят в проекте. Я лично за первый, т.к. идет разделение на уровне форматирования на оператор, идущий без отбивки, и его операнды, идущие с отбивкой слева. В твоем же случае два оператора, = и +, отбиты по разному. Хотя логика понятна «сложение 'внутри' присвоения».
                                                                  0
                                                                  >Читаемость должна находится на первом месте.

                                                                  Согласен, вот только представления о ней у каждого свои :)

                                                                  >Многословность форматирования легко может фикситься через минификацию/обфускацию на этапе сборке проекта. В контексте php это сборка в phar файл(ы).

                                                                  Обычно это не нуждается в фиксе. А сборка php-проекта, по-моему, очень редкий зверь. Я так его наблюдал только когда пробовал HAML прикрутить к PHP из спортивного интереса.
                                                                    0
                                                                    Редкий, просто потому что народ на это тупо забивает/не думает. Это как быдлокодинг. Но сбор проекта в один файл дает неплохой прирост. Поэтому я лично считаю этот аспект на столько важным, что хочу включить сборку в единый phar файл в своем проекте.
                                                                      0
                                                                      Информации о плюсах мало, а привычные сценарии разработки, разворачивания, обновления и поддержки (читай — правка кода на сервере :) ) ломает.

                                                                      А вообще я больше не о phar (тут-то понятно, без сборки никуда), а вещах вроде «инлайна» инклудов, минимизации html, css и js, то есть препроцессинге и компиляции не в рантайме.
                                                              +2
                                                              А зачем у вас перед FROM отступ? По логике ведь, эта строка не менее (а то и более) первостепенна, чем INNER JOIN.
                                                                0
                                                                Сложно писсать код в камментариях, размер отступов в textarea отличается на отображении, не заметил :)
                                                                  +2
                                                                  Кстати, я в WHERE отступы делаю по той же самой логике, вот так:

                                                                  SELECT *
                                                                  FROM tbl
                                                                  INNER JOIN tratata
                                                                    ON zozo.zozo = zaza
                                                                  WHERE a = 1
                                                                    AND z = 1000
                                                                  

                                                                  В случае с AND условия получаются ещё и выстроены на одном уровне.
                                                                    +1
                                                                    Да, это разумнее. Я на самом деле так же пишу, спеша видимо перепутал, так удобнее бегать по концу строк, менять value, когда играешься с запросами, так же более выражены AND OR и прочее.
                                                                      0
                                                                      А я так пишу, удобней комментировать условия для отладки.

                                                                      SELECT
                                                                      tb1.*,
                                                                      tb2.*
                                                                      FROM
                                                                      tb1
                                                                      left join tb2 on tb1.id = tb2.id
                                                                      WHERE
                                                                      tb1.`date` = '2012-06-15' and
                                                                      tb2.`date` = '2012-06-15' and
                                                                      tb1.cat = 1
                                                                        0
                                                                        Я в последнее время после where всегда единицу ставлю, так удобней если какое-то условие закомментить нужно:
                                                                        SELECT *
                                                                        FROM tbl
                                                                        INNER JOIN tratata
                                                                          ON zozo.zozo = zaza
                                                                        WHERE 1
                                                                          AND a = 1
                                                                          AND z = 1000
                                                                        
                                                                  –4
                                                                  В аду есть специальный котел для тех, кто пишет открывающую фигурную скобку на новой строке :-)
                                                                    +2
                                                                    Хм, если честно, я сам всегда писал открывающую фигурную скобку на той же строке, где и сама функция, но сейчас я ограничен стандартами компании :)
                                                                      +3
                                                                      … и он пустует, потому что такие люди в ад не попадают? :)
                                                                      Если серьёзно, то вот это уж точно является делом привычки. А также, традиций. В Java принято ставить открывающую фигурную скобку на той же строке, в C# — переносить.
                                                                        0
                                                                        Насколько я помню ядро люнекса написано на таких скобках. Давным дано еще когда не было нормальных иде. так было удобней смотреть где открывается функция или условие и где заканчивается. Вот оттуда и понеслось.
                                                                          +1
                                                                          Соблюдение стандартов кодирования важнее субъективного мнения о них. Главное чтобы в одном контексте было одинаково, например для классов и методов на новой строке ставить, а для if, for и т. п. в той же.
                                                                            +3
                                                                            Есть как минимум три соглашения о расстановке фигурных скобок в коде:

                                                                            BSD style:
                                                                            if(x == y)
                                                                            {
                                                                              something();
                                                                            }


                                                                            GNU style:
                                                                            if (x == y)
                                                                              {
                                                                                something ();
                                                                              }


                                                                            K&R style:
                                                                            if (x == y) {
                                                                              something();
                                                                            }


                                                                            Какой из них использовать — зависит от соглашений, принятых в компании либо заданных самим языком.
                                                                            К примеру, в Perl согласно Perl Best Practices рекомендуется использовать K&R style.
                                                                              0
                                                                              Не редкость и комбинация, когда для одних конструкций (функций, классов, методов например) используется один (BSD), а для других (управление потоком) — другой (K&R).
                                                                              • UFO just landed and posted this here
                                                                              0
                                                                              В аду есть специальный котел для тех, кто разводит такие холивары.

                                                                              Мое мнение — главное, чтобы везде было одинаково. И пох, с новой строки, или на той же строке.
                                                                              +7
                                                                              А не хватит ли уже на Хабре писать однотипные статьи по оформлению кода?

                                                                              Никакой новой инфы, которой не было в over 9000 таких же статей на тему «Как именовать переменные, методы и ставить отступы»
                                                                                0
                                                                                ага, читаешь интернет — и действительно, зачем столько однотипных статей, читаешь чужой код и понимаешь, что таких статей слишком мало, а каждому второму разработчику нужно стучать МакКоннелом по голове, чтобы не писал щуйни вроде
                                                                                uuU_NEW+=uuUold-uuOLD
                                                                                  0
                                                                                  Вы подождите, еще про табы/пробелы никто не заикался…
                                                                                  OH SHI~…
                                                                                  0
                                                                                  Согласитесь, читать такой код:

                                                                                  Более приятно, чем


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

                                                                                  P.S. Интересно, кстати, что раньше подобного за собой не замечал и сам всё всегда расписывал построчно.
                                                                                    0
                                                                                    может в очень простом коде, где всего пара переменных и будет проще читать, если он будет написано в пару строк, но вы представьте, если такой код будет везде: методы классов, модели и так далее. Поэтому лучше сразу придерживаться определенных правил
                                                                                    +2
                                                                                    > либо порядку их использования внутри метода

                                                                                    Странное правило. Вы предлагаете, чтобы сигнатура метода была завязана на его реализацию? А как же инкапсуляция? А если метод переопределяется, и в переопределённом методе порядок другой?

                                                                                    Вообще публичные методы должны быть определены в интерфейсах, где «использование внутри метода» вообще не предполагается, а порядок параметров в непубличных не так важен.
                                                                                      +1
                                                                                      К названиям методов, возвращающих boolean, полезно применять тоже правило что к boolean переменным. А именно:

                                                                                      file->checkViruses()

                                                                                      vs.

                                                                                      file->isVirusFree()
                                                                                      или
                                                                                      file->hasVirus()
                                                                                        0
                                                                                        Имена булевых переменных должны быть в утвердительной форме и подразумевать булево значение: done, error, found, finished. Плохо: status, source.

                                                                                        можно еще добавлять is: isDone, isError, isFound
                                                                                          0
                                                                                          Is иногда грамматически не подходит. К примеру, document.hasErrors, objects.areEqual, page.willBeRemoved
                                                                                            0
                                                                                            Один из лучших комментариев, что я видел за последнее время.
                                                                                          +2
                                                                                          Можно было бы ограничиться последний ссылкой.
                                                                                            0
                                                                                            Ребята (и автор) — это, конечно, все очень хорошо, копья ломаны не раз.
                                                                                            Хотел бы заметить совсем другое: нужно при оформлении кода ориентироваться на читающих, а не на всех.
                                                                                            То есть, если это мой единоличный проект, то его код, скорей всего не будут читать (зачем? рынок и без того перенасыщен приложениями и библиотеками), поэтому, имхо, глупо его красиво оформлять. Он должен удовлетворять лично мои потребности.
                                                                                            Если я пишу в команде, то неважно какой там кодстайл используется, важно, чтобы он был и был один. Читать его будет только команда. Новички скорее привыкнут к не очень им нравящемуся стилю, не нужно угождать им.
                                                                                            Если проект с открытыми исходными кодами… Думаю, аналогично. Конечно, потенциально его будут читать больше «левых» людей, но это как бы уже их проблемы.

                                                                                            Т.е. «я не 10$, чтобы всем нравиться» и «овчинка выделки не стоит».
                                                                                              0
                                                                                              Правила оформления кода вносят в продукт примерно такой же вклад, как и геометрическая правильность кирпичей в готовый дом :) Хорошо когда они примерно одинаковы. Но бессмысленно добиваться абсолютной точности.

                                                                                                0
                                                                                                Вот только на практике проще добиться абсолютной точности чем примерной (это и про кирпичи и про программирование).
                                                                                                –2
                                                                                                Добавлю от себя немножко:

                                                                                                1. Старайтесь избегать условных компиляций, да исключением #indef в заголовках. Если же угораздило вляпаться в мешанину #if, #ifdef, #else и т. п., то старайтесь делать условные блоки как можно короче, оформляйте операторы условной компиляции отступами и (желательно) подробными комментариями.

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

                                                                                                3. Вместо реального кода используйте как можно чаще константы, вычисляемые во время компиляции.

                                                                                                4. Для бекапа и обмена кодом используйте систему управления версиями (SVN, Git, Merqurial).

                                                                                                5. Уделяйте время для ведения сопроводительного дневника проекта — простого текстового файла, где делайте наброски алгоритмов, кратко записывайте, какие изменения были сделаны, описание проблем, замечания по оставшейся работе (todo).
                                                                                                  –2
                                                                                                  Не используйте табуляцию для оформления кода, заменяйте её пробелами.
                                                                                                  Абсолютная ересь.
                                                                                                  Есть code convention, им определяется все.
                                                                                                    +1
                                                                                                    Табуляция объективно хуже тем, что не имеет постоянной ширины. В результате код, красиво выровненный с табами = 4 пробела, превращается в дикую лесенку при табах = 2 пробела.

                                                                                                    Если нет иных code conventions, использую 2 пробела. Опыт показывает, что это идеал.
                                                                                                      0
                                                                                                      Табуляция объективно хуже
                                                                                                      Что русскому здорово, то немцу смерть.
                                                                                                      Ваше суждение субъективно. Срача на тему «tab vs space» здесь было достаточно, не хочется устраивать очередной.
                                                                                                      Используйте, что угодно, только не возводите это в разряд абсолютной истины.
                                                                                                  0
                                                                                                  Переходя к практике: может кто-нибудь посоветовать настраиваемую утилиту форматирования кода? Потому что всё описанное (в части оформления кода) — это хорошо, но когда стандартные IDE не помогают вообще, сложно разношерстную команду подбить под одни правила. Или там, унаследовав от предыдущей команды сотню классов в произвольном форматировании, не хочется терять часы на форматирование ручками.
                                                                                                  P.S. У меня конкретно MatLab, но я готов потратить время на конфигурацию готового продукта. Писать с нуля парсер не готов.
                                                                                                    0
                                                                                                    Наши соглашения о кодировании включают рекомендации из книги Герба Саттера и Андрея Александреску:
                                                                                                    Стандарты программирования на C++. 101 правило и рекомендация.
                                                                                                      0
                                                                                                      Кроме обеспечения удобочитаемости, соглашения должны служить цели снижения количества ошибок.

                                                                                                      К примеру такое объявление переменных у нас запрещено, т.к. приводит к ошибкам:
                                                                                                      int someCounter, someOtherValue = 0;
                                                                                                      

                                                                                                      или условные операторы без скобок также запрещены, т.к. можно дописать что-то, а скобки забыть:
                                                                                                      if (someValue == 0)
                                                                                                          WriteTrace("Before do something"); // эта строчка была добавлена позже
                                                                                                          DoSomething(); // ошибка, этот код будет вызываться даже если someValue != 0
                                                                                                      

                                                                                                      Но снижение ошибок не должно быть важнее удобочитаемости, и по этому мы не следуем рекомендации писать константы перед переменными в сравнениях:
                                                                                                      if (ERROR_SUCCESS != GetLastError()) // IMHO, снижает читабельность кода
                                                                                                      
                                                                                                        0
                                                                                                        Некоторые соглашения утверждают, что нужно обязательно ставить звездочку возле имени переменной, а не возле типа, т.к. это может привести к проблемам в следующей конструкции:
                                                                                                        int *somePointer, *anotherPointer;
                                                                                                        

                                                                                                        Но так, как у нас однострочное объявление запрещено, то мы спокойно пишем так, как нам удобно:
                                                                                                        int* somePointer;
                                                                                                        int* anotherPointer;
                                                                                                        
                                                                                                        0
                                                                                                        Спорные моменты по форматированию, такие как на какой строчке ставить скобку, либо где ставить пробелы, у нас принимались простым голосованием, т.к. нет четких доводов ни за ни против какого-либо варианта. В конечном итоге это не так ужи и важно, главное чтобы был один стиль в рамках проекта.
                                                                                                          0
                                                                                                          Еще, думаю, не стоит пытаться описывать в соглашениях все и сразу, стоит начать с малого. Также после некоторого времени становится ясно, что некоторые правила стоит изменить.
                                                                                                          Соглашения — это живой документ, который развивается вместе с командой разработчиков, и отражает накопленный опыт.

                                                                                                        Only users with full accounts can post comments. Log in, please.