Сообщество по SharePoint на facebook

Исторически так сложилось, что для общения всех заинтересованных людей по SharePoint не было единой площадки в Интернет.

Были и есть форумы на GotDotNet.ru (сейчас лежит) и MSDN\Technet, но оба сфокусированы на вопрос-ответ и населены новичками, которые пытаются сделать что-то нехорошее.

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

Присоединяйтесь к https://www.facebook.com/groups/sharepointrussian/



Улучшаем экспорт в Excel для SharePoint

Стандартная возможность экспорта в Excel в SharePoint работает довольно необычным образом. При нажатии на кнопку экспорта SharePoint отдает файл запроса в специальном формате, который открывается Excel и  уже сам Excel затягивает данные.

Преимущество такого подхода в том, что данные в Excel можно обновить, так как есть соединение. Но недостатков больше:

  1. Нужен установленный Excel на компьютер, чтобы получить данные.
  2. В полученном документе для названий колонок используется InternalName полей.
  3. В полученном документе используется “сырой” формат данных, что далеко не всегда подходит.

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

Подмена кнопок экспорта

Чтобы заменить существующий элемент в Ribbon надо добавить новый CommandUIDefinition с параметром Location равным Id существующего элемента. Все стандартные элементы находятся в файле C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\GLOBAL\XML\CMDUI.XML для SharePoint 2010 (или 15 для SharePoint 2013).

Для того, чтобы подменить кнопки экспорта в Excel надо найти кнопки с Id равными Ribbon.List.Actions.ExportToSpreadsheet и Ribbon.Library.Actions.ExportToSpreadsheet и полностью скопировать в свой проект. В качестве Location для новых элементов надо указать эти Id.

<CommandUIDefinitions>
  <CommandUIDefinition
    Location="Ribbon.Library.Actions.ExportToSpreadsheet">
    <Button Id="Ribbon.Library.Actions.ExportToSpreadsheet-Replacement"
      Sequence="40"
      Command="ExportToSpreadsheet-Replacement"
      Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-152" Image16by16Left="-32"
      Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-352" Image32by32Left="0"
      LabelText="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipTitle="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipDescription="$Resources:core,cui_STT_ButExportListToSpreadsheet;"
      TemplateAlias="o2"
        />
  </CommandUIDefinition>
  <CommandUIDefinition
    Location="Ribbon.List.Actions.ExportToSpreadsheet">
    <Button Id="Ribbon.List.Actions.ExportToSpreadsheet-Replacement"
      Sequence="40"
      Command="ExportToSpreadsheet-Replacement"
      Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-152" Image16by16Left="-32"
      Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-352" Image32by32Left="0"
      LabelText="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipTitle="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipDescription="$Resources:core,cui_STT_ButExportListToSpreadsheet;"
      TemplateAlias="o1"
        />
  </CommandUIDefinition>
</CommandUIDefinitions>

Есть еще отдельная кнопка для календаря с Id="Ribbon.Calendar.Calendar.Actions.ExportToSpreadsheet", с ней можно сделать тоже самое.

Создание контрола

Кнопка должна вызывать некоторый серверный код. Чтобы поведение было аналогично стандартной кнопке лучше всего сделать DelegateControl, который будет размещаться на каждой странице. Для этого есть контейнер с Id="AdditionalPageHead"

<Control 
  Id="AdditionalPageHead"
  Sequence="1000"
  ControlAssembly="$SharePoint.Project.AssemblyFullName$" 
  ControlClass="$SharePoint.Type.7fd7c6f0-4eda-48ce-ac8f-aa9f9d2666ac.FullName$"/>

Кастомная кнопка будет вызывать PostBack, обрабатываемый нашим контролом. Кнопка может быть нажата на странице представления списка, тогда не надо передавать дополнительных параметров на сервер. Представления списков могут быть добавлены на обычные страницы как веб-части, тогда нужно передать Id списка и представления на сервер.

Увы, получение Id представления, в котором была нажата кнопка – нетривиальная задача. Поэтому я ограничусь только передачей Id списка.

<CommandUIHandlers>
  <CommandUIHandler
    Command="ExportToSpreadsheet-Replacement"
    CommandAction="javascript:(function(){var x=SP.ListOperation.Selection.getSelectedList(); if (x) {__doPostBack('ExportToSpreadsheet-Replacement', x);}})();" />
</CommandUIHandlers>

Далее на сервере нужно проверить нажата ли кнопка на странице представления списка или на обычной странице:

protected override void OnLoad(EventArgs e) { 
    if (this.Page.Request["__EVENTTARGET"] == "ExportToSpreadsheet-Replacement") 
    {
        var spContext  = SPContext.Current;
        SPList list;
        SPView view;

        if (spContext.ViewContext.View != null)
        {
            list = spContext.List;
            view = spContext.ViewContext.View;
        }
        else
        {
            var listId = new Guid(this.Page.Request["__EVENTARGUMENT"]);
            var web = spContext.Web;
            list = web.Lists[listId];
            view = list.DefaultView;
        }

        ExportData(list.Title + " - " + view.Title, GetDataTable(list, view));
    } 
}

 

Получение таблицы данных по представлению очень просто:

private static System.Data.DataTable GetDataTable(SPList list, SPView view)
{
    var query = new SPQuery(view);
    SPListItemCollectionPosition position;
    var flags = SPListGetDataTableOptions.UseBooleanDataType | SPListGetDataTableOptions.UseCalculatedDataType;
    var result = list.GetDataTable(query, flags, out position);
    while (position != null)
    {
        list.AppendDataTable(query, flags, result, out position);
    }
    return result;
}

Генерация Excel файла

Последним шагом требуется сформировать Excel файл и отдать его клиенту. Один из самых простых способов сгенерировать Excel – использовать библиотеку ClosedXml (http://closedxml.codeplex.com/).

private void ExportData(string title, System.Data.DataTable table)
{
    var wb = new XLWorkbook();
    var ws = wb.Worksheets.Add(title);
    ws.Cell(1, 1).InsertTable(table);

    var response = this.Page.Response;
    response.Clear();

    response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    var filename = title+".xlsx";
    response.AddHeader("content-disposition", GetContentDisposition(filename));

    // Flush the workbook to the Response.OutputStream
    using (var memoryStream = new MemoryStream())
    {
        wb.SaveAs(memoryStream);
        memoryStream.WriteTo(response.OutputStream);
    }
    response.End();
}

 

Первые три строки метода собственно формируют Excel документ (спасибо ClosedXml), а все остальное – код для отдачи файла клиенту.

Заголовок ответа content-disposition очень по-разному воспринимается разными браузерами, поэтому отдать файл с корректным русским именем требует некоторых танцев с бубном.

Код для формирования корректного заголовка content-disposition я нашел на StackOverflow http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http

private string GetContentDisposition(string filename)
{
    var request = this.Page.Request;
    string contentDisposition;
    if (request.Browser.Browser == "IE" && (request.Browser.Version == "7.0" || request.Browser.Version == "8.0"))
        contentDisposition = "attachment; filename=" + Uri.EscapeDataString(filename);
    else if (request.UserAgent != null && request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
        contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(filename) + "\"";
    else
        contentDisposition = "attachment; filename=\"" + filename + "\"; filename*=UTF-8''" + Uri.EscapeDataString(filename);
    return contentDisposition;
}

private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c);
private string MakeAndroidSafeFileName(string fileName)
{
    char[] newFileName = fileName.ToCharArray();
    for (int i = 0; i < newFileName.Length; i++)
    {
        if (!AndroidAllowedChars.ContainsKey(newFileName[i]))
            newFileName[i] = '_';
    }
    return new string(newFileName);
}

Заключение

Чтобы все заработало на Production надо добавить файлы ClosedXml.dll и DocumentFormat.OpenXml.dll в ваш пакет. Кнопки Ribbon и контрол поместить в одну фичу уровня Site или Web.

Весь проект можно посмотреть по ссылке - https://spsamples.codeplex.com/SourceControl/latest#ExportToExcel/

Готовый WSP файл тут - https://spsamples.codeplex.com/releases/view/117220



Как обычно делают корпоративный портал на SharePoint

Недавно на facebook был опубликован (не мной) просто эпичный пост про корпоративный портал на SharePoint. Поиска по постам на facebook нет, поэтому приведу содержание здесь:

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

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

В понедельник меня будит звонок руководителя, который сообщает, что портал не работает. При чем весь и полностью. До этого у нас были проблемы с главной страницей, но мы их успешно решили. А тут умерло вообще все. Ни один сайт не открывается. Исследования показали, что серваки просто не справляются с нагрузкой: очередь в IIS как при СССР за докторской колбасой, а памяти она жрет больше обычного раза в три. Кое-как продравшись в layouts, меняю мастер-страницу на дефолтную и наследую её для всех узлов. Портал моментально взлетает. Почти. Весь, кроме главной страницы. Выяснилось, что на главной странице masterpage жестко прописан в коде. Так как подрядчиков было уже не достать, оставил всё как есть и почти счастливо пошел отмечать новый год.

Сегодня танцы с бубном продолжили уже подрядчики. Код их, деньги уже уплочены, так что пусть свои косяки и исправляют. И что в итоге? А всё очень просто. В masterpage оказалась вшита веб-часть, которая подгружала курсы валют с сайта cbr.ru, но подгружала она не на серверной стороне, а на клиентской без какого-либо кеширования. В итоге, админы cbr получив с одного IP 100 000+ запросов за менее чем рабочий день, банально нас забанили. Веб-часть же начала ругаться на отсутствие аутентификации. А так как написана она была левой пяткой, то ругалась до бесконечности, не позволяя подгрузить о стальной контент страницы. Баг, который может проявиться только при опытной эксплуатации и на тестах его выявить практически нереально.

Автор поста – админ, не программист, но хорошо разбирается в SharePoint. Поэтому оставим технические детали вроде серверной\клиентской стороны для веб части (судя по симптомам загрузка курсов была именно на сервере).

Первоначально все накинулись на подрядчиков с рекомендациями писать try\catch. Но ошибка, вероятнее всего, была вызвана как раз использованием try с пустым catch (без throw) в цикле. Ошибка довольно типичная для среднестатистического разработчика SharePoint. Но самое важное в этой истории как раз то, что не написано и не касается подрядчиков вообще.

Какая необходимость вообще возникла пихать информер курсов валют на все страницы всех сайтов портала? От этого есть реальный value? Даже в финансовых организациях от силы 30% сотрудников будут получать преимущество от такого функционала, но у них, скорее всего, будет специальный софт, где будут и курсы валют и многое другое. А в среднестатистической организации курсы валют на каждой странице не нужны никому, а если вдруг кому-то понадобятся, то они быстрее зайдут на сам cbr.ru.

Коммент на тему откуда вообще появились курсы валют:

Курсы валют все равно есть и в 1С и на всяких яндексах и т.д. Но партия (руководство) сказала надо, значит надо.

Это прекрасно! Полтора года назад у меня уже был пост на тему создания решений, где тоже все свелось к мифическому “руководству”. Значит и подходы, описанные  в моем посте, остаются такими же верными.

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

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

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

Ну и корень всей этой ситуации:

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

Без комментариев...

Резюме

Вот так обычно делают порталы на SharePoint:

  1. Выбирают по красивой картинке (проблема заказчика).
  2. Не работают с требованиями (проблема заказчика).
  3. Полное отсутствие менеджмента проекта на стороне заказчика (понятно чья проблема).
  4. Полное отсутствие контроля качества на стороне заказчика (аналогично) .
  5. Подрядчики не обладают достаточной квалификацией по созданию порталов (по сути единственная проблема подрядчиков).
  6. У заказчика вообще нет стратегии внедрения и развития портала.

При этом все ругаются именно на подрядчиков. Хотя даже с плохими подрядчиками можно делать хорошие проекты, при нормальном менеджменте у заказчика.

Если же нет специалистов у заказчика, то обязательно нужно нанимать консультантов ДО начала проекта. Это позволит сэкономить гораздо больше денег.



Как сделать хороший корпоративный портал

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

Взгляд ИТшника

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

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

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

Взгляд дизайнера

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

Но корпоративный портал – не сайт-визитка. Когда ИТшники пытаются впихнуть на портал функционал (все таки портал – ИТ актив), то дизайн портала начинает “плыть”. Контент, необходимый чтобы поддерживать красивость дизайна, оказывается создавать очень сложно и этим никто не занимается.

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

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

Взгляд архитектора

Здесь речь пойдет об Information Architect, но на адекватного перевода на русский я не нашел.

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

Архитекторы стремятся сделать портал удобным и понятным, но без помощи дизайнеров не могут сделать его привлекательным для пользователей, а без помощи ИТ – полезным.

Так как большинство Information Architect занимаются документооборотами, то даже портал в их представлении больше похож на файлопомойку. Очень структурированную, управляемую, с хорошей навигацией, поиском, механизмами compliance, но файлопомойку.

Взгляд бизнесмена

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

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

Естественно лояльность и продуктивность для всех сотрудников разом увеличить не получится. Для начала нужно четко определить цели, желательно по методике SMART. Для каждой цели должны быть метрики достижения, а также целевая аудитория пользователей, релевантная данной цели. Целевая аудитория (aka сегмент пользователей) далеко не всегда будет соответствовать организационным единицам или должностям.

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

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

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

Заключение

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



Как важно писать хороший код

Мне приходится очень много читать код. Это и open source, и всяческие фреймворки, и код enterprise приложений. Именно о последних я хотел бы сегодня поговорить.

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

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

Теория разбитых окон

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

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

Есть также и обратный эффект. Поддержание порядка приводит к тому, что окружающие также поддерживают порядок.

Как это влияет на код

В enterprise разработке прессинг сроков и неопределенности требований бывает настолько высок, что кажется сделать “быстро и грязно” – гораздо лучший вариант, чем сделать правильно. Моментально подход “быстро и грязно” начинает распространяться по всему приложению, как путем clipboard inheritance (aka copy-paste), так и за счет эффекта разбитых окон.

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

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

В open source и продуктовой разработе такое встречается реже. Там больше следят за качеством и меньше прессинг сроков.

Код пишется для людей

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

Хороший код должен, в первую очередь, очень ясно выражать намерения. К сожалению “быстрые и грязные” способы разработки бьют в первую очередь по понимаемости кода. Улучшение кода осознанно откладывается до лучших времен, когда будет пауза чтобы провести рефакторинг. Те самые лучшие времена никогда не наступают, а код начинают читать и дорабатывать сразу же после попадания в source control.

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

Приверженность качеству

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

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

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

Если вам приходится править код, то не создавайте хаков. Потратьте немного времени, напишите нормально. Сэкономите на поддержке. Если же код совсем плохой, был сделан “быстро и грязно” и оброс хаками, то просто выкиньте его и перепишите. Только не надо пытаться переписать все. Учитывайте продуктивность: программист пишет 40-60 отлаженных строк кода в день в нормальном темпе и 120-200 в ускоренном (высокая концентрация, четкая цель, понятно что делать).

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

Если вы скопировали часть кода из другого места или, не дай бог, из интернета, то разберитесь как он работает, прежде чем заливать изменения в source control. Вообще не используйте непонятные вас фрагменты кода.

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

Перечитывайте свой код. Проводите рефакторинг постоянно в процессе написания. Помните, что рефакторинг “потом” никогда не наступает. 

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

Экономика качества кода

Все знакомы с кривой стоимости ошибки:

Ошибка найденная и устраненная на этапе кодирования в 10 раз дешевле, чем ошибка найденная при тестировании и в 100 раз дешевле ошибки, найденной в production. В истории есть реальные примеры ошибок, исправление которых обошлось в десятки тысяч долларов.

Поэтому очень важно устранять ошибки на этапе разработки, причем усилиями самих разработчиков.

На последок

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