Скрипт для создания документов Google из источника данных электронной таблицы Google

Microsoft Office поддерживает «источники данных» для генерации, например. Письма, счета-фактуры, адресные наклейки и другие повторяющиеся документы на основе шаблона Microsoft Word и данных Microsoft Excel. Это очень распространенная проблема малого бизнеса, и у Office есть решение для нее с середины 90-х годов. Google Apps, облачная альтернатива Microsoft Office, не предлагает подобную функциональность изначально (или, по крайней мере, если они действительно скрывают ее). Тем не менее, вы можете легко создать собственный генератор документов, используя сценарии Google Apps, если вы владеете программированием. В этом блоге я покажу пример, как создать такой скрипт и изучить основы скриптов Google Apps.

1. Ингредиенты генератора документов

У нас есть следующие материалы для нашей бизнес-проблемы

  • Электронная таблица Google Apps, содержащая данные о клиентах.
  • Документ шаблона документов Google. На основе этого мы хотим сгенерировать документ для каждого клиента, заполнив этот шаблонный документ данными из электронной таблицы.
  • Папка на Google Диске, в которой хранятся полученные документы.
  • Скрипт Google Apps, который автоматизирует задачу для нас (на основе Javascript)

Все они хранятся в вашей учетной записи Google Apps на Google Диске. Все редактирование происходит через пользовательский интерфейс Google Apps, никаких внешних инструментов не требуется.

Все они хранятся в вашем аккаунте Google Apps в Google Drive. Все редактирование происходит с помощью Служб Google пользовательского интерфейса, без каких-либо внешних инструментов, необходимых.

Пример исходных данных (затемненный с obfuscate.js )

Пример шаблона документа (затемненный с obfuscate.js ). Вы можете видеть исходные метки источника, незаполненные.

Пример результирующего документа – метки , заполненные и больше не выделены жирным шрифтом (затемненный с obfuscate.js )

2. Краткое введение в Google Apps Script

Скрипты Google Apps можно запускать двумя способами

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

Скрипт  Google  apps- это сценарий JavaScript (версия ECMAScript неизвестна? Запущен ли V8?), который обеспечивает простые способы автоматизации задач в продуктах Google и сторонних службах. Скрипт  Google apps содержит обширную документацию API с примерами и учебными пособиями, но они по-прежнему подвержены значительным изменениям, поскольку почти все отмечено как экспериментальное и уже существует много устаревших методов. Скрипты Google Apps могут также получать доступ к Картам Google, контактам, электронной почте, сайтам, настройкам домена Google Apps и в основном иметь решение для автоматизации почти все, что вы можете делать в облаке Google.

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

Философия и паттерны проектирования пользовательского интерфейса представляют собой шаг назад к 90-м годам, к среде сценариев Visual Basic. Возможно, разработчики Google Apps хотели этого … чтобы разработчики Visual Basic чувствовали себя как дома. Однако из-за веб-разработки, Javascript и общего фона программирования вы обнаружите отсутствие Firebug / Web Inspector, например, нарушение работы консоли. Это не похоже на какую-либо другую разработку Javascript, хотя, безусловно, синтаксис такой же.

Поэтому мои незначительные жалобы включают, но не ограничиваются этим:

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

Отладчик в действии

Все могло быть лучше, но в итоге мне удалось сделать то, что я искал, и я все еще не плачу ни копейки за Google Apps, поэтому я счастлив. Кроме того, я не хочу возвращаться в Microsoft Office, если мне не нужно писать хорошо отформатированные документы для печати … Документы Google – это игрушка, которая приходит к тяжелому и графически чувствительному авторингу документов, как предложения …. Или презентации … где Keynote – король.

3. Скрипт генератора

В начале скрипта у вас есть константы, которые определяют, по каким данным работать. Вы можете создать пользовательский интерфейс, делающий скрипт для полного веб-приложения, но это слишком громоздкий подход для такой небольшой задачи. Конструктор пользовательского интерфейса казался приятным, но определенно излишним. Хотя в браузере существуют методы API сценариев Google Apps для выполнения простого запроса prompt (), по какой-то причине они не поддерживались в автономных сценариях … поэтому самый быстрый подход для ввода данных в скрипт заключался в том, чтобы просто редактировать сценарий перед каждым запуском. Я ооочень начал пропускать командную строку … первый раз в моей жизни.

Итак, в начале скрипта вы определяете исходные данные

  • Идентификатор электронной таблицы (вы можете выбрать его из URL-адреса при редактировании документа)
  • Идентификатор документа шаблона (вы можете выбрать его из URL-адреса при редактировании документа)
  • Идентификатор клиента, который является номером строки таблицы, для текущего запуска скрипта.
  • Идентификатор папки для драйверов Google, куда будет помещен полученный документ для совместного использования. Опять же, вы можете выбрать идентификатор из URL-адреса при открытии папки.

Затем скрипт просто заменяет слова данными. Ключевое слово, подлежащее замене в документе шаблона, идентифицируется как метки столбцов (1-я строка) в данных электронной таблицы. Я вполне уверен, что для этого были бы более эффективные методы, но я не хотел тратить время на то, чтобы поглубже нанести удар по GS, чтобы выяснить его нюансы.

А затем сценарий … пожалуйста, не стесняйтесь модифицировать в соответствии с вашими потребностями (generator.gs):

/**
 * Generate Google Docs based on a template document and data incoming from a Google Spreadsheet
 *
 * License: MIT
 *
 * Copyright 2013 Mikko Ohtamaa, http://opensourcehacker.com
 */

// Row number from where to fill in the data (starts as 1 = first row)
var CUSTOMER_ID = 1;

// Google Doc id from the document template
// (Get ids from the URL)
var SOURCE_TEMPLATE = "xxx";

// In which spreadsheet we have all the customer data
var CUSTOMER_SPREADSHEET = "yyy";

// In which Google Drive we toss the target documents
var TARGET_FOLDER = "zzz";

/**
 * Return spreadsheet row content as JS array.
 *
 * Note: We assume the row ends when we encounter
 * the first empty cell. This might not be 
 * sometimes the desired behavior.
 *
 * Rows start at 1, not zero based!!! ?
 *
 */
function getRowAsArray(sheet, row) {
  var dataRange = sheet.getRange(row, 1, 1, 99);
  var data = dataRange.getValues();
  var columns = [];

  for (i in data) {
    var row = data[i];

    Logger.log("Got row", row);

    for(var l=0; l<99; l++) {
        var col = row[l];
        // First empty column interrupts
        if(!col) {
            break;
        }

        columns.push(col);
    }
  }

  return columns;
}

/**
 * Duplicates a Google Apps doc
 *
 * @return a new document with a given name from the orignal
 */
function createDuplicateDocument(sourceId, name) {
    var source = DocsList.getFileById(sourceId);
    var newFile = source.makeCopy(name);

    var targetFolder = DocsList.getFolderById(TARGET_FOLDER);
    newFile.addToFolder(targetFolder);

    return DocumentApp.openById(newFile.getId());
}

/**
 * Search a paragraph in the document and replaces it with the generated text 
 */
function replaceParagraph(doc, keyword, newText) {
  var ps = doc.getParagraphs();
  for(var i=0; i<ps.length; i++) {
    var p = ps[i];
    var text = p.getText();

    if(text.indexOf(keyword) >= 0) {
      p.setText(newText);
      p.setBold(false);
    }
  } 
}

/**
 * Script entry point
 */
function generateCustomerContract() {

  var data = SpreadsheetApp.openById(CUSTOMER_SPREADSHEET);

  // XXX: Cannot be accessed when run in the script editor?
  // WHYYYYYYYYY? Asking one number, too complex?
  //var CUSTOMER_ID = Browser.inputBox("Enter customer number in the spreadsheet", Browser.Buttons.OK_CANCEL);
  if(!CUSTOMER_ID) {
      return; 
  }

  // Fetch variable names
  // they are column names in the spreadsheet
  var sheet = data.getSheets()[0];
  var columns = getRowAsArray(sheet, 1);

  Logger.log("Processing columns:" + columns);

  var customerData = getRowAsArray(sheet, CUSTOMER_ID);  
  Logger.log("Processing data:" + customerData);

  // Assume first column holds the name of the customer
  var customerName = customerData[0];

  var target = createDuplicateDocument(SOURCE_TEMPLATE, customerName + " agreement");

  Logger.log("Created new document:" + target.getId());

  for(var i=0; i<columns.length; i++) {
      var key = columns[i] + ":"; 
      // We don't replace the whole text, but leave the template text as a label
      var text = customerData[i] || ""; // No Javascript undefined
      var value = key + " " + text;
      replaceParagraph(target, key, value);
  }

}
 

 

Как критиковать компьютерщиков или избегать неэффективной амортизации оскорблений

Original version: https://www.cs.purdue.edu/homes/dec/essay.criticize.html

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

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

Два основных типа исследований

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

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

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

Комплексная теория и простые системы

Знание традиции, из которой исходит исследователь, дает основание для целенаправленного оскорбления.

Теоретики предпочитают изощренность

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

Экспериментаторы предпочитают простоту

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

Критика

Знания, что CS можно разделить на две основные группы, очень помогают при критике кого-то. Существует два основных правила: определить тип исследователя и выдать оскорбление для этого типа. Избегайте говорить что-либо, что неосторожно хвалит их. Если все будет хорошо, оскорбление не только ошеломит исследователя (кто будет потрясен, узнав, что не все согласны с его базовой системой ценностей), но и запугает других в аудитории.

Идентификация типа А

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

Обнаружение теории

Вы можете сказать, что кто-то является теоретиком, потому что он пропускает один или несколько следующих ключевых слов и фраз в лекции и технические беседы: «теорема», «лемма», «доказательство», «аксиома», «полиномиальное время», «логарифмический», «семантика», «числовой», «сложность», «недетерминированный» или «недетерминизм» и «при достаточно большом N». Они пишут много уравнений, хвастаются о том, чтобы сбить «дополнительный лог-фактор», и часто заканчивают свою лекцию прописной «О», за которой следует математическое выражение, заключенное в круглые скобки. Вы также можете признать теоретика, потому что он вечно доказывает то, что может показаться совершенно очевидным. (Однажды я просидел часовую лекцию, где кто-то доказал, что после того, как компьютер выполнил оператор присваивания, который поместил целое число 1 в переменную х, значение в х было равно 1.)

Обнаружение систем

Экспериментатор пропустит один или несколько следующих ключевых слов и фраз в лекции и технические беседы: “ архитектура ”, “ память ”, “ `cpu ” (иногда сокращенное` `CISC ” или` `RISC ” ), “ I / O ” или “ bus ”, “ network ”, “ interface ”, “ virtual ”, `compile ” или` `compiler ”,` OS ‘ «Система», «распределенная», «программа» или «код» и «бинарный». Они рассказывают о создании программ и запуске результирующей системы на реальных компьютерных системах. Они относятся к компаниям и продуктам, и используют акронимы либерально. Их лекции часто заканчиваются графиком или диаграммой измеряемой производительности системы. Вы также можете распознать экспериментатора, потому что они в мучительных подробностях описывают, как они настраивают эксперимент для измерения определенного значения, даже если измерение дает точно ожидаемые результаты. (Однажды я просидел часовую лекцию, где кто-то тщательно объяснял, как они использовали три компьютерные системы для измерения сетевого трафика, когда их все было просто в том, чтобы показать, что сеть не является причиной проблемы, которую они изучают.)

Формирование оскорбления

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

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

Разве это не просто прямое продолжение старого результата Хартманиса? (Даже Хартманис не помнит все теоремы Хартманиса, но все остальные будут считать, что вы помните то, что они забыли.)

Я что-то пропустил? Можете ли вы определить какой-либо глубокий математический контент в этой работе? (Вновь участники аудитории, которые посчитали трудным для понимания разговор, не захотят это признать).

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

Разве это не было сделано много лет назад в Xerox PARC? (Никто не помнит, что действительно было сделано в PARC, но все остальные будут считать, что вы помните то, чего они не делают.)

Испытали ли вы это на чипе, который Intel выпустил на прошлой неделе в своей лаборатории? (Никто не знает, какой чип Intel запущен на прошлой неделе, но все будут считать, что вы это сделали).

Я что-то упускаю? Не очевидно ли, что в системе есть узкое место, которое предотвращает масштабирование до произвольного размера? (Это безопасно, потому что в каждой системе есть узкое место, которое предотвращает произвольное масштабирование.)

Как избежать оскорбления в ответ на вас

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

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

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

Никогда не пытайтесь атаковать системы просто, говоря, что это настолько просто и очевидно, что вы могли бы это сделать. (В течение многих лет люди говорили о UNIX и протоколах TCP / IP). Фактически, это просто расширение уловки, используемой детьми на игровой площадке: «Ах, да? Я мог бы это сделать, если бы захотел. »« Не пытайтесь использовать это, или кто-то скажет вам расти.

Нападение кроссоверов

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

Я отмечаю, что системный аспект этого проекта кажется довольно сложным. Считаете ли вы, что причина запутанной реализации может быть связана с более или менее «упрощенным» математическим анализом, который вы использовали?

Однако умное оскорбление может не говорить о работе, предлагая зловещие причины сдвига парадигмы:

Я замечаю, что вы сделали что-то необычное, объединив как теорию, так и эксперимент. Вы решили попробовать второй подход, потому что у вас не было результатов с первого раза?

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

Заключительная просьба

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

 

PuTTY для win32, сохраняющий конфигурацию в файл

Original version: http://jakub.kotrla.net/putty/

Информация


Недавно несколько Antivirus SW пометили двоичные файлы на этом сайте , как вредоносные программы. Это ложный положительный результат . Я сам компилирую двоичные файлы: сначала загрузите исходный код с веб-сайта PuTTY, перезапишите код хранения сессии и скомпилируйте с помощью Visual Studio. Используемый ПК чист.

  Причина может быть более строгие правила и эвристика AV из-за- за http://www.securityweek.com/attackers-use-trojanized-version-putty-steal-ssh-credentials . Я скомпилировал тот же код plink.exe в режиме Release и Debug – результаты AV сильно отличаются из-за расплывчатого эвристического соответствия версии Release.

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

I fully understand if you do not trust me – feel free to compile the binaries yourself.


PuTTY – отличный бесплатный клиент telnet / ssh для платформ Win32 и Unix. Это всего лишь один «exe», без установки, никаких дополнительных библиотек DLL не требуется. Таким образом, он может запускаться с дискеты, USB-флеш-диска и т. Д.

Но он сохраняет всю конфигурацию в реестре ([HKEY_CURRENT_USER \ Software \ SimonTatham \ PuTTY]) – вы не можете сохранить / загрузить его из файла на дискете или других съемных устройствах. Есть обходной путь с файлами bat / reg, но это не очень приятно. Поэтому я переписал небольшую часть PuTTY (winstore.c – функции, которые обрабатывают конфигурацию сохранения / загрузки).

Я также переписал небольшую часть Pageant, чтобы иметь возможность загрузить список сохраненных сеансов (winpgnt.c – function update_sessions).

Если вы обнаружили ошибку, связанную с хранением / загрузкой конфигурации или отсутствием в исходном PuTTY, не стесняйтесь отправить ее по электронной почте jakub@kotrla.net. Моя модификация PuTTY находится под той же лицензией, что и PuTTY – вы можете делать что угодно с этим, но на свой страх и риск и без каких-либо гарантий.

Документация

Этот PuTTY хранит свою конфигурацию (сеансы, ключи хоста ssh, путь к файлу случайных семян) в файл вместо реестра. Каждый сеанс и ключ хоста ssh хранятся в отдельном файле. Пути по умолчанию (где. Представляет исполняемый каталог):

  • ./sessions/ packedSessionName
  • ./sshhostkeys/ packedHostName
  • ./putty.rnd

Путь для сохранения конфигурации может быть установлен через файл putty.conf. Сначала выполняется поиск в текущем рабочем каталоге, если там не найден putty.conf, выполняется исполняемый каталог (тот же каталог, что и для putty / pscp / psftp / plink / pageant.exe). Putty.conf должен выглядеть так (если он не найден, по умолчанию используются значения):

;comment line
sessions=%SYSTEMROOT%\ses
sshhostkeys=\ssh\hostkeys
seedfile=C:\putty.rnd
sessionsuffix=.session
keysuffix=.hostkey
jumplist=jumplist.txt

Вы можете использовать переменные окружения в config (например,% SYSTEMROOT%) – строка будет расширена через функцию WinAPI ExpandEnviromentString (переменные, зависящие от пользователя, пока не поддерживаются).

Sessionuffix и keysuffix являются необязательными, значения по умолчанию пустые. Если установлено, каждый файл имеет определенный суффикс (сохраненные сеансы через sessionuffix и ключи ssh host через keyuffix). Основная цель – избегать файлов «* .com» с именами, например ssh.domain.com. Оба числа ограничены 15 символами.
Внимание: Если вы уже сохранили некоторые сеансы или ключи хоста SSH и изменили эти суффиксы, вам придется вручную переименовать (добавить их) во все файлы.

Jumplist – новая функция в Windows 7, поддерживаемая PuTTY 0.61. Поскольку этот PuTTY должен быть легким, если вы не укажете путь к jumplist, ни один из них не будет создан.

Этот PuTTY все еще может загрузить конфигурацию из реестра. Сессии, загруженные из реестра, помечены как [registry]. Когда PuTTY проверяет ключ хоста ssh и он не найден в файле, но в реестре, вы можете переместить / скопировать ключ в файл (или, конечно, ничего не делать).

Pageant загружает список сохраненных сеансов из пути, установленного в putty.conf, по умолчанию ./sessions/packedSessionName – он работает так же, как и PuTTY (включая настройку keysuffix).

ChangeLog

Этот PuTTY все еще развивается, так как в первом простом выпуске я добавил некоторые функции и исправил несколько ошибок. Итак, я только начал нумерацию версий. Здесь будут представлены все будущие изменения, особенности и исправления.

  • 24. 11. 2005 – первая версия 0.1.1
  • 22. 3. 2006 – PSCP, PSFTP скомпилирован и добавлен
  • 22. 3. 2006 – исправлена Pageant работать с sessionsuffixправильно (версия 0.1.2)
  • 7. 8. 2006 – исправлена ​​PSCP при загрузке несуществующих параметров беззвучно и нулевая ручка ошибки фиксированных (версия 0.1.3)
  • 9. 8. 2006 – гораздо лучше, обнаружение “putty.exe каталог” добавлена ​​(версия 0.1.5)
  • 29. 9. 2006 – Plink скомпилирован и добавлен
  • 9. 1. 2007 – исправлен для сохранения / загрузки настроек по умолчанию (версия 0.1.6)
  • 25. 1. 2007 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.59 и незначительные утечки памяти фиксирован (версия 0.2)
  • 24. 3. 2007 – Поддержка переменных окружения в конфигурационном файле и код очистки (версия 0.2.1)
  • 1. 5. 2007 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.60 (версия 0.3)
  • 15. 10. 2007 – исправлен показ “” и «..» сессии в списке сессии (версия 0.3.1)
  • 6. 3. 2008 – Исправлен сбой, если файл конфигурации не заканчивается пустой строкой (версия 0.3.2)
  • 12. 8. 2008 – так как теперь: изменения в обработке putty.conf и работы / исполняемых каталогов
  • 4. 9. 2008 – конкурс начинается putty.exe в его (театрализованном в) рабочий каталог и XP и Vista, визуальные стили поддерживаются (версия 0.3.5)
  • 28. 7. 2009 – фиксированная сессия делеция когда sessionsuffix установлен в PuTTY (версия 0.3.6)
  • 4. 9. 2009 – если seesion не найден на диске, попробуйте в реестре (для поддержки WinSCP), исправлены мелкие ошибки с CurrentDirectory (версия 0.3.7)
  • 7. 11. 2009 – Поддержка переменных окружения в файлах сессии (версия 0.3.8)
  • 12. 1. 2010 – исправлена ​​загрузка сессии с именами, содержащими двоеточие (:) и другие странные символы (версия 0.3.9)
  • 24. 8. 2011 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.61 (версия 0.4), поддержка Win7 Jumplist
  • 23. 2. 2012 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.62 (версия 0.5)
  • 8. 9. 2013 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.63 (версия 0.6)
  • 13. 9. 2013 – Исправлена ​​ошибка из слияния коды с 063 – погрузочными сеансами из реестра фиксированного (версия 0.6.1)
  • 8. 3. 2015 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.64 (версия 0.7), файлы сеансов фильтруются sessionsuffix
  • 27. 9. 2015 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.65 (версия 0.8)
  • 27. 9. 2015 – Обновление: этот модифицированный PuTTY теперь основан на снимке PuTTY развития 2015-09-27.acff0a6 предоставить некоторые новые шифры например ed25519 кривые и chacha20. (Версия 0.8.1)
  • 18. 11. 2015 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.66 (версия 0.9)
  • 6. 12. 2015 – Обновление: этот модифицированный PuTTY теперь основан на снимке PuTTY развития 2015-11-30.1659cf3 предоставить некоторые новые шифры например ed25519 кривые и chacha20. (Версия 0.9.1)
  • 19. 3. 2016 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.67 (версия 0.10.0) и развития снимка 2016_03_18.0fadffe
  • 6. 11. 2016 – перекомпилировать в режиме отладки, чтобы избежать ложных срабатываний перестраховщика Антивирусное ПО
  • 20. 3. 2017 – Обновление: этот модифицированный PuTTY теперь основан на PuTTY 0.68 (версия 0.11.0)

О написании: правила Хайнлайна

Original version: http://www.sfwriter.com/ow05.htm


Есть бесчисленные правила написания успеха, но самые известные из них, по крайней мере в области научной фантастики, – это пятерка, созданная покойным великим Робертом А. Хайнлайном.

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

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

Я собираюсь поделиться с вами пятью правилами Хайнлайна, плюс добавить свою шестую.


 

Правило первое: вы должны написать

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

И не смейте  жаловаться, что у тебя нет времени писать. Настоящие писатели покупают время, если они не могут получить его каким-либо другим способом. Возьмите уроженца Торонто Теренса М. Грина, учительницу средней школы. Его третий роман «Тень Ашленда» вышел из Тора. Терри каждый пятый год учится без платы, чтобы он мог писать; Большинство писателей, которых я знаю, приносили такие же жертвы за свое искусство.

(Из наших сотен оригинальных кандидатов-аспирантов половина никогда не сможет обойтись без написания чего-либо. Это оставит нам пятьдесят …)


 

Правило второе. Закончите то, что вы начинаете.

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

В связи с этим: если вы принадлежите к мастерской писателей, не позволяйте людям критиковать ваш роман за раз. Никто не может должным образом судить о книге по части, вырванной из нее наугад, и вы получите всевозможные бессмысленные советы: «Эта часть кажется неуместной». «Ну, на самом деле, на самом деле, это очень важно сотня страниц с этого момента …»

(Из наших пятидесяти оставшихся потенциальных авторов половина никогда не закончит что-либо – оставив только двадцать пять все еще на ходу …)


 

Правило третье: вы должны воздерживаться от перезаписи, кроме редакционного заказа

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

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

И хотя многие новички не верят в это, Хайнлайн прав: если ваша история близка к публикации, редакторы расскажут вам, что вам нужно сделать, чтобы сделать ее доступной. Некоторые журналы из небольших газет делают это подробно, но вы также получите рекомендации от Analog, Asimov’s и The Magazine of Fantasy & Science Fiction.

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


 

Правило четвертое: вы должны разместить свою историю на рынке

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

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

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

(Из наших двенадцати авторов осталось, половина из них не будет работать на нервы, чтобы сделать представление, оставив только шесть …)


 

Правило пятое: вы должны держать его на рынке, пока он не продан

Это факт: работа постоянно отвергается. Почти наверняка ваше первое представление будет отклонено. Не позволяйте этому останавливать вас. В настоящее время я получил 142 отскока в моих файлах; У каждого профессионального писателя, которого я знаю, есть стеки из них (плодовитый канадский писатель-ужастик Эдо ван Белком отлично говорит на съездах SF под названием «Процветание отторжения», в котором он читает образцы из многих, которые он приобрел за эти годы).

Если в отклонении есть совет, который, по вашему мнению, хорош, пересмотрите историю и отправьте ее снова. Если нет, то просто переверните историю: вытащите ее по почте, отправив ее на другой рынок. Держись! Не сдавайся. Мой собственный рекорд по максимальному количеству представлений перед продажей истории – восемнадцать, но история, в конце концов, нашла хороший дом. (И через несколько дней я снова продал его в передовой только антологию, получив рассказ в печати, впервые открыв все новые рынки).

Если ваша история отвергнута, отправьте ее в тот же день на другой рынок.

(Тем не менее, из наших шести оставшихся авторов три будут настолько обескуражены этим первым отказом, что они бросят писать навсегда, но еще три будут держаться на нем …)


 

Правило шестое: начните работать над чем-то еще

Это мое правило. Я видел слишком много начинающих писателей в течение многих лет над одной историей или романом. Как только вы закончите одну часть, начните с другой. Не ждите, пока первый рассказ вернется из редактора, в который вы его отправили; Приступайте к работе над следующим проектом. (И если вы обнаружите, что испытываете блок писателя в своем текущем проекте, начните писать что-то новое – настоящий писатель может всегда что-то написать.) Вы должны создать массу работы, чтобы считать себя настоящим профессионалом.

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


По словам Маклина: Канады Weekly Newsmagazine , «По любой расплате Роберт Сойер является одним из самых успешных канадских авторов , когда – либо.» Он продал 23 романов в крупных американских издателей и получил 53 национальных и международных наград за его фантастики, в том числе фикция Общества World Science Hugo Award и научной фантастики и фэнтези писателей Америки премии Nebula за лучший роман года, а также Преступность Писатели Канады премии Артур Эллис за лучший рассказ года. Сериал ABC Вспомни был основан на его романе того же самого имени.

Роб преподавал творческое письмо в Университете Торонто, Райерсон университет, Хамбер колледж, и Центр Банф, и он был писателем-в-резиденции в Торонто, Ричмонд Хилл, и Китченер публичных библиотек и в канадском источник света, Канады национальный синхротрон. Он часто основной докладчик на конференциях писателей.

Более подробную информацию о Робе и его работе, увидеть его веб – сайт sfwriter.com , который содержит 800 документов и более одного миллиона слов материала.

 

Непрерывная интеграция

Это перевод публикации «Непрерывная интеграция»
Автор: Мартин Фаулер
Original version: http://www.martinfowler.com/articles/continuousIntegration.html

8 апреля 2013

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

содержание

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

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

Это различие не является результатом дорогостоящих и сложных инструментов.  Суть его заключается в простой практике каждой команды интегрирующей часто, как правило , ежедневно с контролируемым исходным хранилища.
Когда я описывал эту практику людям, я обычно нахожу две реакции: «она не может работать (здесь)» и «делать это не будет иметь большого значения». То, что люди узнают, когда они пробуют это, – это намного проще, чем кажется, и это имеет огромное значение для развития. Таким образом, третья общая реакция – «да, мы делаем это – как бы вы могли жить без нее?»

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

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


Построение объекта с непрерывной интеграцией

Самый простой способ объяснить, что такое CI и как это работает, – показать быстрый пример того, как он работает с разработкой небольшой функции. Предположим, что я должен что-то сделать для части программного обеспечения, на самом деле не имеет значения, что это за задача, на данный момент я предполагаю, что она небольшая и может быть выполнена за несколько часов. (Мы рассмотрим более длинные задачи и другие вопросы позже.)

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

Вышеупомянутый параграф будет иметь смысл для людей, которые используют системы управления исходным кодом, но будьте бредовыми для тех, кто этого не делает. Поэтому позвольте мне быстро объяснить, что для последнего. Система управления исходным кодом хранит весь исходный код проекта в репозитории. Текущее состояние системы обычно называется «магистралью». В любое время разработчик может сделать контролируемую копию магистрали на своей собственной машине, это называется «проверка». Копия на компьютере разработчика называется «рабочей копией». (В большинстве случаев вы действительно обновляете свою рабочую копию на основной – на практике это то же самое.)

Теперь я беру свою рабочую копию и делаю все, что мне нужно для выполнения моей задачи. Это будет состоять как в изменении производственного кода, так и в добавлении или изменении автоматических тестов. Непрерывная интеграция предполагает высокую степень автоматизации, которая автоматически включается в программное обеспечение: объект который я называю   автоматическое тестирование кода .  Часто они используют версию популярных платформ тестирования XUnit.

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

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

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

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

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

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


Практика непрерывной интеграции

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

Ведение единого хранилища исходного кода.

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

Поэтому, как простая основа, убедитесь, что вы получаете достойную систему управления исходным кодом. Стоимость не является проблемой, поскольку доступны качественные инструменты с открытым исходным кодом. Текущий репозиторий с открытым исходным кодом по выбору – Subversion. (Старый инструмент с открытым исходным кодом CVS по-прежнему широко используется и намного лучше, чем ничего, но Subversion – это современный выбор.) Интересно, что, разговаривая с разработчиками, я знаю, что большинство коммерческих инструментов управления исходным кодом любят меньше, чем Subversion. Единственный инструмент, который я постоянно слышал от людей, заслуживающих оплаты, это Perforce.

Как только вы получите систему управления исходным кодом, убедитесь, что это известное место для всех, чтобы получить исходный код. Никто никогда не должен спрашивать: «Где файл foo-whiffle?» Все должно быть в репозитории.

Хотя многие команды используют хранилища общей ошибка , которую я вижу в том , что они не ставят все на хранении. Если люди используют , кто будет ставить код там, но все , что вам нужно сделать сборку должны быть там, в том числе: тестовые сценарии, файлы свойств, схемы базы данных, устанавливать скрипты и сторонние библиотеки.  Я знаю , что проекты , которые обеспечивают , чтобы их составители в репозиторий (важно в первые дни компиляторы листа C + +).  Основное правило заключается в том , что вы должны быть в состоянии идти в проект девственницы машины, полная проверка, и быть в состоянии в полной мере развивать систему.  Только минимальное количество вещей , которые должны быть на машине дев – в основном вещи , которые являются большей, сложной установкой и стабильной.  Операционная система, среда разработки Java, или базовая система управления базами данных являются типичными примерами.

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

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

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

Сборка автоматизации

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

Автоматизированная среда для сборок – общая черта систем. Мир Unix существует уже несколько десятилетий, сообщество Java разработало Ant, сообщество .NET имеет Nant и теперь имеет MSBuild. Убедитесь, что вы можете создавать и запускать вашу систему, используя эти скрипты, используя одну команду.

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

Скрипты сборки входят в различные вкусы и часто являются специфическими для платформы или сообщества, но они не обязательно должны быть. Хотя в большинстве наших Java-проектов используется Ant, некоторые использовали Ruby (система Ruby Rake – очень хороший скриптовый скрипт). Мы получили большую выгоду от автоматизации раннего проекта Microsoft COM с помощью Ant.

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

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

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

Сделайте свою сборку самопроверкой

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

Хороший способ быстрее и эффективнее выявлять ошибки – включить автоматические тесты в процесс сборки. Конечно, тестирование не является совершенным, но оно может перехватить множество ошибок – достаточно, чтобы быть полезным. В частности, появление Extreme Programming (XP) и Test Driven Development (TDD) сделало много для популяризации кода самотестирования, и в результате многие люди увидели ценность этой техники.

Постоянные читатели моей работы будут знать, что я большой поклонник как TDD, так и XP, но я хочу подчеркнуть, что ни один из этих подходов не нужен для получения преимуществ кода самотестирования. Оба этих подхода делают точкой написания тестов перед тем, как вы напишете код, который их пропускает – в этом режиме тесты в равной мере касаются изучения дизайна системы, так как они касаются ловушки ошибок. Это хорошая вещь, но для целей Continuous Integration нет необходимости, когда у нас есть более слабое требование самотестирования кода. (Хотя TDD является моим предпочтительным способом создания кода самотестирования).

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

За последние несколько лет, TDD рост популяризировал  XUnit семьи с  открытым исходным кодом, которые идеально подходят для такого рода испытаний.  Инструменты XUnit оказались очень ценными для нас на ThoughtWorks, и я всегда предлагаю людям, чтобы они ими пользовались. Эти инструменты, разработанные Kent Beck, облегчают вам настройку среды самодиагностики.

Инструменты XUnit, безусловно, являются отправной точкой для самостоятельного тестирования вашего кода. Вам также следует обратить внимание на другие инструменты, которые фокусируются на более комплексном тестировании, в настоящее время существует целый ряд таких факторов, включая FIT, Selenium, Sahi, Watir, FITnesse и множество других, в которых я не являюсь Пытаясь всесторонне перечислить здесь.

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

Все коммиты фиксируются в основную ветку

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

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

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

Тот факт, что вы строите при обновлении рабочей копии, означает, что вы обнаруживаете конфликты компиляции, а также текстовые конфликты. Поскольку сборка является самотестированием, вы также обнаруживаете конфликты в работе кода. Последние конфликты – особенно неудобные ошибки, чтобы найти, долго ли они сидят в коде. Поскольку между фиксацией изменений всего несколько часов, есть только очень много мест, где проблема может скрываться. Кроме того, поскольку не так много изменилось, вы можете использовать diff-debugging, чтобы помочь вам найти ошибку.

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

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

Каждый Commit нужно построить магистраль на интеграционной машине

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

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

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

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

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

На ThoughtWorks мы являемся большими поклонниками серверов с непрерывной интеграцией – действительно, мы возглавили оригинальную разработку CruiseControl и CruiseControl.NET, широко используемых CI-серверов с открытым исходным кодом. С тех пор мы также создали коммерческий Cruise CI сервер. Мы используем сервер CI почти в каждом проекте, который мы делаем, и были очень довольны результатами.

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

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

Исправить поврежденные сборки немедленно

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

Фраза, которую я помню с использованием Кента Бека, заключалась в том, что «никто не имеет более приоритетной задачи, чем исправление сборки». Это не означает, что все в команде должны остановить то, что они делают, чтобы исправить сборку, обычно требуется всего лишь пара людей, чтобы заставить вещи работать снова. Это означает сознательную приоритизацию исправления сборки как неотложной и высокоприоритетной задачи.

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

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

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

Быстрое создание сборки

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

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

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

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

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

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

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

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

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

Тестирование в клоне производственной среды

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

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

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

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

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

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

Одна из самых сложных составляющих разработки программного обеспечения – это то, что вы создаете правильное программное обеспечение. Мы обнаружили, что очень сложно заранее определить, что вы хотите, и быть верным; Людям гораздо легче увидеть что-то не совсем правильное и сказать, как его нужно изменить. Гибкие процессы разработки явно ожидают и используют в своих интересах эту часть человеческого поведения.

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

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

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

Каждый может видеть, что происходит

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

Одной из важных вещей для общения является состояние сборки магистрали. Если вы используете Cruise, есть встроенный веб-сайт, который покажет вам, есть ли в процессе сборки и каково было состояние последней сборки mainline. Многим командам нравится делать это еще более очевидным, подключая непрерывный показ к системе сборки – свет, который светится зеленым, когда работает сборка, или красный, если он не работает, популярны. Особенно часто встречаются красные и зеленые лавовые лампы – не только они показывают состояние сборки, но и то, как долго она находится в этом состоянии. Пузыри на красной лампе указывают на то, что сборка была сломана слишком долго. Каждая команда делает свой собственный выбор на этих датчиках построения – хорошо быть игривым с вашим выбором (недавно я видел, что кто-то экспериментировал с танцующим кроликом).

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

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

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

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

Автоматизация развертывания

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

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

Если вы внедрите в производство еще одну автоматическую функцию, которую вы должны рассмотреть, это автоматический откат. Время от времени случаются плохие вещи, и если вонючие коричневые вещества попадают на вращающийся металл, хорошо иметь возможность быстро вернуться к последнему известному хорошему состоянию. Возможность автоматического возврата также уменьшает напряженность развертывания, побуждает людей к более частому развертыванию и, таким образом, быстро выводит новые функции пользователям. (Сообщество Ruby on Rails разработало инструмент под названием Capistrano, который является хорошим примером инструмента, который делает подобные вещи.)

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

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


Преимущества непрерывной интеграции

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

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

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

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

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

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

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

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


Введение в непрерывной интеграции

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

Здесь нет фиксированного рецепта – многое зависит от характера вашей установки и команды. Но здесь есть несколько вещей, которые мы научились делать.

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

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

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

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

Прежде всего, получите некоторую помощь. Найдите того, кто сделал непрерывную интеграцию, чтобы помочь вам. Как и любой новый метод, его трудно представить, если вы не знаете, как выглядит конечный результат. Это может стоить денег, чтобы получить наставника, но вы также заплатите потерянное время и производительность, если вы этого не сделаете. (Отказ / Реклама – да, мы в ThoughtWorks делаем некоторые консультации в этой области. В конце концов мы сделали большую часть ошибок, которые мы можем сделать).


заключительные мысли

За годы, прошедшие с тех пор, как Мэтт и я написали оригинальную статью на этом сайте, Continuous Integration стала основным методом разработки программного обеспечения. Вряд ли любой проект ThoughtWorks обходится без него – и мы видим, что другие используют CI во всем мире. Вряд ли я когда-либо слышал негативные вещи об этом подходе – в отличие от некоторых из наиболее противоречивых методов экстремального программирования.

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


дальнейшее чтение

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

Чтобы подробнее изучить непрерывную интеграцию, я предлагаю взглянуть на соответствующую книгу Пола Дюваля по этой теме (которая получила награду Jolt – больше, чем я когда-либо управлял). Чтобы узнать больше о более широком процессе Непрерывной поставки, взгляните на книгу Джеза Хамбла и Дэйва Фарли, которые также избили меня до награды Jolt.

Оригинальная версия: http://www.martinfowler.com/articles/continuousIntegration.html

Utilu Mozilla Firefox

 Original version: https://utilu.com/UtiluMFC/
Коллекция Utilu Mozilla Firefox содержит несколько автономных версий Mozilla Firefox, которые можно использовать одновременно.
Utilu Mozilla Firefox Collection – это утилита, разработанная Utilu, которая содержит несколько версий бесплатного браузера Mozilla Firefox, которые являются автономными, поэтому их можно использовать одновременно. Это полезно для веб-разработчиков.


Mozilla Firefox является зарегистрированной торговой маркой Mozilla Foundation .

Применение

В Utilu Mozilla Firefox Collection вы можете быстро увидеть , как ваши сайты выглядят при визуализации с использованием различных версий Gecko движок рендеринга. Вы можете указать имена файлов или местоположение (URL) , чтобы открыть в нескольких установленных версиях Mozilla Firefox . Кроме версии для открытия могут быть выбраны.

Имена файлов или URL-адреса, которые включают в себя пробелы, должны быть заключены в кавычки ( “). Несколько имен файлов или URL-адреса могут быть использованы, разделяя их пробелами. Это приведет к несколько вкладок открывается.

Ввод, например,

“C: \ Directory \ Local file.html” http://mozilla.com/ https://utilu.com/

в поле ввода будет открыть локальный файл и два URL-адрес в трех вкладках в установленных версиях Mozilla Firefox, которые могут быть выбраны в следующем шаге.

Если вы хотите, чтобы открыть страницу по умолчанию введите просто «по умолчанию» в поле ввода.

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

Из командной строки можно также указать пути и имена файлов или URL – адрес в качестве параметров Utilu Mozilla Firefox Collection (UtiluMFC.exe), в этом случае интерфейс не будет отображаться , но настроенные версии Mozilla Firefox запускаются непосредственно с указанными путями и имена файлов или URL – адреса был открыт в закладках. Пример:

UtiluMFC.exe http://mozilla.com/ https://utilu.com/

По умолчанию будут открыты специфицированные имена файлов или URL – адреса в версиях Mozilla Firefox , выбранных ранее. Вместо того , чтобы использовать эти ранее настроенные версии вы также можете указать версии Mozilla Firefox вы хотите открыть из командной строки с помощью параметра -SelectedVersions = сопровождаемые версии Mozilla Firefox , чтобы открыть, разделенные запятой. Пример:

UtiluMFC.exe -SelectedVersions = 2.0,3.0,3.5,3.6,17.0esr, 24.0esr, 32,0 https://utilu.com/

Дополнительная информация

Номер версии каждой включенной версии Mozilla Firefox можно найти в заголовке окна.

Utilu Mozilla Firefox Collection также включает в Firebug и Web Developer дополнение для всех включенных версий Mozilla Firefox. Эти дополнения обеспечивают различные инструменты , которые делают по устранению неполадок веб – сайтов гораздо проще.

Установка

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

Utilu Mozilla Firefox Collection полностью поддерживает обновление, поэтому нет необходимости удалять предыдущую версию перед установкой новой версии: просто установить новую версию поверх текущей установленной версии с тем же или более компонентов , выбранных.

Укажите параметр -setDefaultBrowser к установщику , чтобы сделать его установить Mozilla Firefox в качестве браузера по умолчанию.

Utilu Mozilla Firefox Collection доступен только на английском языке.

Utilu Mozilla Firefox Collection в первую очередь предназначен для веб – разработчиков. Обычные пользователи могут лучше использовать Utilu Silent Setup for Mozilla Firefox.

версии Mozilla Firefox

Utilu Mozilla Firefox Collection содержит следующие версии Mozilla Firefox:

  • Mozilla Firefox 2.0.0.20
  • Mozilla Firefox 3.0.19.0
  • Mozilla Firefox 3.5.19.0
  • Mozilla Firefox 3.6.28.0
  • Mozilla Firefox 4.0.1.0
  • Mozilla Firefox 5.0.1.0
  • Mozilla Firefox 6.0.2.0
  • Mozilla Firefox 7.0.1.0
  • Mozilla Firefox 8.0.1.0
  • Mozilla Firefox 9.0.1.0
  • Mozilla Firefox 10.0.2.0
  • Mozilla Firefox ESR 10.0.12.0
  • Mozilla Firefox 11.0.0.0
  • Mozilla Firefox 12.0.0.0
  • Mozilla Firefox 13.0.1.0
  • Mozilla Firefox 14.0.1.0
  • Mozilla Firefox 15.0.1.0
  • Mozilla Firefox 16.0.2.0
  • Mozilla Firefox 17.0.1.0
  • Mozilla Firefox ESR 17.0.11.0
  • Mozilla Firefox 18.0.2.0
  • Mozilla Firefox 19.0.2.0
  • Mozilla Firefox 20.0.1.0
  • Mozilla Firefox 21.0.0.0
  • Mozilla Firefox 22.0.0.0
  • Mozilla Firefox 23.0.1.0
  • Mozilla Firefox 24.0.0.0
  • Mozilla Firefox 24.8.1.0 СОЭ
  • Mozilla Firefox 25.0.1.0
  • Mozilla Firefox 26.0.0.0
  • Mozilla Firefox 27.0.1.0
  • Mozilla Firefox 28.0.0.0
  • Mozilla Firefox 29.0.1.0
  • Mozilla Firefox 30.0.0.0
  • Mozilla Firefox 31.0.0.0
  • Mozilla Firefox 31.8.0.0 СОЭ
  • Mozilla Firefox 32.0.3.0
  • Mozilla Firefox 33.0.3.0
  • Mozilla Firefox 33.1.1.0
  • Mozilla Firefox 34.0.0.0
  • Mozilla Firefox 35.0.1.0
  • Mozilla Firefox 36.0.4.0
  • Mozilla Firefox 37.0.2.0
  • Mozilla Firefox 38.0.6.0
  • Mozilla Firefox 38.8.0.0 ESR
  • Mozilla Firefox 39.0.3.0
  • Mozilla Firefox 40.0.3.0
  • Mozilla Firefox 41.0.2.0
  • Mozilla Firefox 42.0.0.0
  • Mozilla Firefox 43.0.4.0
  • Mozilla Firefox 44.0.2.0
  • Mozilla Firefox 45.0.2.0
  • Mozilla Firefox 45.8.0.0 ESR
  • Mozilla Firefox 46.0.1.0
  • Mozilla Firefox 47.0.1.0
  • Mozilla Firefox 48.0.2.0
  • Mozilla Firefox 49.0.2.0
  • Mozilla Firefox 50.0.2.0
  • Mozilla Firefox 50.1.0.0
  • Mozilla Firefox 51.0.1.0
  • Mozilla Firefox 52.0.1.0
  • Mozilla Firefox 52.0.1.0 ESR
  • Mozilla Firefox 53.0.0.0 beta 4
  • Mozilla Firefox 54.0.0.0 Aurora
  • Mozilla Firefox 55.0.0.0 Nightly

Mozilla Firefox дополнения и плагины

Utilu Mozilla Firefox Collection содержит следующие дополнения и плагины:

  • Firebug 1.3.1 дополнения для Mozilla Firefox 2.0
  • Firebug 1.4.5 дополнения для Mozilla Firefox 3.0
  • Firebug 1.5.4 дополнения для Mozilla Firefox 3.5
  • Firebug 1.7.3 дополнения для Mozilla Firefox 3.6 и 4.0
  • Firebug 1.9.2 дополнения для Mozilla Firefox 5,0 до 12,0
  • Firebug 1.10.6 дополнения для Mozilla Firefox 13,0 до 16,0
  • Firebug 1.11.4 дополнения для Mozilla Firefox 17,0 до 22,0
  • Firebug 1.12.8 дополнения для Mozilla Firefox 23,0 до 29,0
  • Firebug 2.0.19 надстройка для Mozilla Firefox 30,0 до 49,0
  • Firebug 3.0.0 дополнения для Mozilla Firefox 49.0 и выше
  • Web Developer 1.1.9 дополнения для Mozilla Firefox 2.0 до 3.5
  • Web Developer 1.2.12 надстройка для Mozilla Firefox 3.6 и выше
  • Flash Player 25.0.0.127 плагин

Дополнительные возможности

Utilu Mozilla Firefox Collection имеет следующие дополнительные функции:

  • Он может открыть один или несколько локальных файлов и / или URL, в указанных установленных версиях Mozilla Firefox с одним нажатием кнопки
  • Она может появиться в контекстном меню Windows Explorer, так что файл может быть открыт в любом выбранной установленной версии Mozilla Firefox напрямую
  • Он может отображать номер версии Mozilla Firefox в заголовке
  • Она включает в себя ряд изменения размера окна опций для веб-разработчика дополнения, настройки для всех общих разрешений, как 800×600, 1024×768, 1280×1024, 1440×900 и 1600х1200 включены
  • Он может быть установлен для всех пользователей, поэтому он доступен для всех
  • Он может быть установлен и использован тихо, можно создать автоматическую установку и использовать все функции, используя параметры командной строки
  • Она работает даже в самых ограниченных учетных записей пользователей после установки, только установка должно быть сделано кем-то с правами администратора
  • Он поддерживает как 32-разрядные, так и 64-разрядные версии Microsoft Windows 98, 98 SE, ME, NT 4.0, 2000, XP, 2003, Vista, 2008, 7, 8, 2012, 8.1, 10 и 2016
  • Обратите внимание, что Mozilla Firefox 13,0 и выше не поддерживают Microsoft Windows 2000 и XP перед тем пакетом обновления 2
  • Обратите внимание, что Flash Player 11 и выше, не поддерживает Microsoft Windows 2000
  • Обратите внимание, что Mozilla Firefox 3.0 и выше и Flash Player 10 и выше, не поддерживают Microsoft Windows 98, 98 SE, ME и NT 4.0

Что нового

Что нового в Utilu Mozilla Firefox Collection 1.1.7.8:

  • Обновление Mozilla Firefox от 52.0.0.0 до 52.0.1.0
  • Обновление Mozilla Firefox от 52.0.0.0 ESR до 52.0.1.0 ESR
  • Обновление Mozilla Firefox от 53.0.0.0 беты 1 до 53.0.0.0 beta 4
  • Обновление Mozilla Firefox 54.0.0.0 Aurora
  • Обновление Mozilla Firefox Nightly 55.0.0.0
  • Обновленный Flash Player от 24.0.0.221 до 25.0.0.127
  • Незначительные изменения и улучшения
Показать список изменения предыдущих версий

Скриншоты

Это позволит установить Utilu Mozilla Firefox Collection 1.1.7.8 на вашем компьютере.

Обслуживает Настройка Mozilla Firefox Collection: Добро пожаловатьОбслуживает Настройка Mozilla Firefox Collection: Добро пожаловать

Настройка Utilu Mozilla Firefox Collection: Выбор компонентовНастройка Utilu Mozilla Firefox Collection: Выбор компонентов

Настройка Utilu Mozilla Firefox Collection: Выбор задачНастройка Utilu Mozilla Firefox Collection: Выбор задач

Настройка Utilu Mozilla Firefox Collection: Готов к установкеНастройка Utilu Mozilla Firefox Collection: Готов к установке

Utilu Mozilla Firefox Collection: Открытые файлы или местаUtilu Mozilla Firefox Collection: Открытые файлы или места

Обслуживает Mozilla Firefox Collection: Выбрать версииОбслуживает Mozilla Firefox Collection: Выбрать версии

Призраки интернет времени

Original version: http://www.praxagora.com/andyo/wr/ghost.html

от Энди Орам
17 декабря 1999 года

В темном свете рассвета мне приснился звук, которого я не слышал долгое время. Громогласно спотыкаясь из-за пронзительного гудка, я воскликнул: «Да ведь это старая дисковая программа Unix! Эта странная небольшая полноэкранная утилита, обсуждаемая Дугласом Хофстаддером в Metamagical Themas, – это предварительно настроенный чат и мгновенный обмен сообщениями. В ответ на буквы, мигающие на зеленом мониторе, я быстро вошел в разговорный призрак и нажал клавишу RETURN.

«Это Призрак интернет-прошлого», написал мой таинственный корреспондент. «NSA, мак, Кастро. Я покажу вам Интернет в его славные первые дни. Тогда инструменты были неуклюжи, но мы все немного учились и учились понимать среду, которую мы использовали; и такое прекрасное сообщество, которое мы создали в Интернете! “

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

«Послушай, Энди, ты тоже был более идеалистичен», – увещевал призрак. «Прошло много лет с тех пор, как вы внесли вклад в проекты бесплатного программного обеспечения. Посмотрите на даты в этих файлах. “Поток имен файлов, дат и размеров потек вниз по экрану.

Я искоса посмотрел на смутно знакомый формат. “Да, эти даты старые. Где ты выкопал этот список?”

«Арчи», – набрал призрак.

«О, Призрак», выдохнул я. «Что случилось с пламенем интернет-сообщества? Почему так мало новичков понимают это? “

«Чего вы ожидаете, когда ANS возьмет на себя хребет?» Выплюнул призрак. «Кантер и Зигель, приятные глазу потоковые медиа».

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

«Проклятый гегемонизм частного сектора …»

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

Затем меня разбудил яростный приступ разговоров. Как будто кто-то запустил сразу несколько дюжин потоков RealPlayer. Лепет многих участников вытеснил всю надежду на понимание. «Кто-нибудь может понять это!» – воскликнул я.

Придя на помощь, голос поднялся над остальными. «Добро пожаловать в дебаты по интернет-политике. Как Призрак Присутствия в Интернете, я должен следовать им всем ».

«О чем они говорят?» – потребовал я.

«Вы имеете в виду: о чем они говорят или о чем они на самом деле говорят?»

«Оба варианта, я думаю», ответил я, невзирая на это.

«Ну, – объяснил призрак, – они думают, что они говорят о том, какая из старых нормативных моделей применима к новому революционному пространству».

«Звучит довольно бессмысленно».

«Вот почему стоит послушать. Но на самом деле речь идет о пропускной способности ».

«Да, я слышал об этом – темное волокно не решит все?»

«Это панацея 90-х годов», презрительно прервал призрак. «Текущее увлечение – это пакетное радио. Но я вовсе не говорил о физической пропускной способности. Я имел в виду контроль. Кто имеет право пользоваться Интернетом? Будут ли на нем размещены объявления о вакансиях для неимущих или только биржевых котировок для богатых? Могут ли сообщества спонтанно вырастать вокруг великих произведений творчества или платить посредникам? Должны ли исследования, финансируемые за счет налогоплательщиков, продаваться за сотни долларов в виде документа или предоставляться свободно всем? С кем можно связаться, просто попросив имя – крупные корпорации или маленькие голоса? “

«Ради всего святого, – воскликнул я, – почему люди так не говорят о проблемах!»

«Как это могло быть – что могло заменить его щедрость?»

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

«А как же демократия? Как насчет общественного пространства? Разве нет форума для среднего гражданина?

Старое морщинистое лицо Призрака треснуло в напыщенном, глухом смехе. “Форум? Вы хотите форум? Я дам вам миллион их. Каждый раз, когда Consolidated Services, Inc. или Skanditek помещают новый пункт в свои СМИ, они оставляют пространство для просмотра реакций. И они публикуют, и публикуют, и публикуют. Никто не может следить за дебатами … “

«Они забыли», – вздохнул я. «Люди забыли, что Интернет позволяет дискуссии и сообщества; они соглашались на чрезмерно прагматичный и безличный подход, который фрагментировал протоколы и СМИ таким образом, чтобы удалить элемент человека. Что я могу сделать, чтобы предотвратить это, Призрак? Скажи мне, что делать, когда я вернусь в свою настоящую жизнь! »

Но туман пронесся над сценой, и рука Призрака будущего Интернета скрылась от меня незримо. «Я угасаю», – прошептал он. «Интернет ушел …»

И поэтому я проснулся, но я лежал с закрытыми глазами и обратился к моим трем Призракам в своих мыслях: «Я обещаю, что пройду все уроки, которые вы сегодня преподали мне!

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

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

«Наконец, Призрак будущего Интернета, я всегда буду настаивать на том, что Интернет является не только средством передачи данных, но и местом для построения сообщества».

И день еще только начинался.

«Несколько попыток, – ответил призрак, – но как только вы присмотритесь к юридическим, социальным и имплементационным последствиям, ответы становятся настолько хорошими, техничными».

Я хотел спросить больше, но мой призрак сказал: «Настоящее мимолетно. Я должен уйти; Призрак будущего Интернета будет здесь вместо меня ».

Меня охватило волнение. «О, Призрак будущего Интернета, – воскликнул я, – покажи мне, какое средство еще предложить!»

Кто-то схватил меня за руку и потащил через лабиринты гремящих улиц под серым небом, где ни одно существо не ступало еще.. «Где будущее в Интернете?» – заорал я. «Куда все пошли?»

«Интернет ушел», сказал мой спутник, сутулый и седой.

 

XSLT скрипт для создания альбомов списка из ITunes XML

Когда я получил себе в IPOD , я нашел , что печатные списки доступны из ITunes программы не были особенно велики (несмотря на интерактивный интерфейс , будучи превосходным), и я не мог получить краткий сводный список альбомов. Поскольку ITunes сохраняет свою библиотеку как XML, я использовал XSLT для создания списка больше по душе. Так как я склонен слушать альбомы , а не синглы, я хотел список альбомов , сгруппированных по жанру .

Чтобы использовать этот сценарий, сохраните albumList.xml и albumList.xsl показано ниже вашей Музыка / ITunes папку, и откройте albumList.xml в Internet Explorer 6+ или Mozilla Firefox (IE5 не будет работать, я не проверял любой другие браузеры).

‘Список свойств’ The Itunes XML

Библиотека ITunes хранится в виде XML в файле под названием ITunes Music Library.xml . Он использует общий язык XML , известный как список свойств или списка свойств , который содержит информацию в виде пар ключ / значение. Вместо того , чтобы быть адаптированы к описанию песен, он может быть использован для описания свойств более или менее ничего. Это как XML выглядит:

<plist version="1.0">
  <dict>
    <key>Tracks</key>
    <dict>
      <key>638</key>
      <dict>
        <key>Track ID</key><integer>638</integer>
        <key>Name</key><string>Take Me To The River</string>
        <key>Artist</key><string>Talking Heads</string>
        <key>Composer</key><string>Al Green &#38; M. Hodges</string>
        <key>Album</key><string>Stop Making Sense</string>
        <key>Genre</key><string>Alternative &#38; Punk</string>
        ... etc ...
      </dict>
    </dict>
  </dict>
</plist>

 

Это означает, что найти, например, название альбома, мы должны соответствовать <string> с непосредственно предшествующим собрата <key> из «Альбома»:

string[preceding-sibling::key[1]='Album']

То есть, элемент <string> где первая <key> в осях предшествующего-родственных имеет значение «Альбом».

Хотя это удобный универсальный язык XML, это, безусловно, сложнее манипулировать, чем язык XML, приспособленный для представления списка дорожек, поэтому сделайте глубокий вдох для того, что следует!

Получение списка альбомов

XML ITunes список песен. Альбом появится песня на это не более, на самом деле, чем атрибут песни, так что простой подход даст название альбома один раз для каждой песни , которая появляется на нем. Таким образом , чтобы получить правильный список альбомов, я использую довольно хитрые трюки , доступные с : <xsl key> элементом и key() и  generate-id()  функций.

Другие люди объяснили использование <xsl: key> лучше, чем я могу, но вкратце, то здесь, то <xsl: key> элемент строит список <dict> узлы, представляющие песни. <xsl:for-each> элемент затем выбирает <dict> (т.е. песня) элементов, в которых автоматически генерируется идентификатор совпадения автоматически созданный идентификатор первого узла, возвращаемого функцией key(). Нет, это делает мою голову спина тоже. Полученная таблица стилей, чтобы получить список альбомов (с прилагаемыми художниками) является:

<xsl:key name="songsByAlbum" match="dict"
  use="string[preceding-sibling::key[1]='Album']"/>

<xsl:template match="/plist/dict/dict">
  <html>
    <body>
      <table>

        <xsl:for-each select="dict[generate-id(.)=
            generate-id(key('songsByAlbum',string)[1])]">
          <xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
          <tr>
            <td><xsl:value-of select="string[preceding-sibling::key[1]='Album']"/></td>
            <td><xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/></td>
          </tr>
        </xsl:for-each>

      </table>
    </body>
  </html>
</xsl:template>

Это имеет проблемы с компиляций, хотя. Он подберет тот, кто является художником для первой песни компиляции, которая выглядит несколько странно. Чтобы это исправить, я использую «Часть Сборник» флаг следующим образом:

<xsl:key name="songsByAlbum" match="dict"
  use="string[preceding-sibling::key[1]='Album']"/>

<xsl:template match="/plist/dict/dict">
  <html>
    <body>
      <table>

        <xsl:for-each select="dict[generate-id(.)=generate-id(key('albums',string)[1])]">
          <xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
          <tr>
            <td><xsl:call-template name="albumName"/></td>
            <td><xsl:call-template name="artistName"/></td>
          </tr>
        </xsl:for-each>

      </table>
    </body>
  </html>
</xsl:template>

<xsl:template name="albumName">
  <xsl:value-of select="string[preceding-sibling::key[1]='Album']"/>
</xsl:template>

<xsl:template name="artistName">
  <xsl:choose>
    <xsl:when test="true[preceding-sibling::key[1]='Compilation']">
      <i>Compilation</i>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

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

Список альбомов сгруппированы по жанру

Проблема с этим списком является то , как музыка всех пюре вместе. Я на самом деле не как иметь страсть Матфея трущиеся плечи с Stop Making Sense .

Чтобы сгруппировать альбомы по жанру, я использую технику, разработанный Стив Муэнч, Oracle, «XML технического евангелист», получившее название «Muenchian группировки».

Опять же , другие люди объяснили это лучше , чем я мог, поэтому достаточно сказать (если вы хотите , чтобы попытаться следовать работы XSL) , который использует функциюgenerate-id()  XSL key , определенных на песни по жанру и Альбом, и в точке , где шаблон albumsInGenre называется, текущий контекст является первым <dict> песня в каждом жанре.

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

Таблица стилей выглядит следующим образом:

<xsl:key name="songsByAlbum" match="dict"
  use="string[preceding-sibling::key[1]='Album']"/>
<xsl:key name="songsByGenre" match="dict"
  use="string[preceding-sibling::key[1]='Genre']"/>


<xsl:template match="/plist/dict/dict">
  <html>
    <body>
      <table>

        <xsl:for-each select="dict[generate-id(.)=
            generate-id(key('songsByGenre',string)[1])]">
          <xsl:sort select="string[preceding-sibling::key[1]='Genre']"/>
          <xsl:for-each select="key('songsByGenre',string)[1]">
            <xsl:call-template name="albumsInGenre">
              <xsl:with-param name="genre"
                  select="string[preceding-sibling::key[1]='Genre']"/>
            </xsl:call-template>
          </xsl:for-each>
        </xsl:for-each>

      </table>
    </body>
  </html>
</xsl:template>


<xsl:template name="albumsInGenre">
  <xsl:param name="genre"/>

  <tr><td colspan='3'><b><xsl:value-of select="$genre"/></b></td></tr>

  <xsl:variable name="song" select="/plist/dict/dict/dict"/>
  <xsl:for-each select="$song[generate-id(.)=
      generate-id(key('songsByAlbum',string[preceding-sibling::key[1]='Album'])[1])]">
    <xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
    <xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
        [string[preceding-sibling::key[1]='Genre']=$genre][1]">
      <tr>
        <td> </td>
        <td><xsl:call-template name="albumName"/></td>
        <td><xsl:call-template name="artistName"/></td>
      </tr>
    </xsl:for-each>
  </xsl:for-each>
</xsl:template>

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

Electronica / Танец
бульвар Сен-Жермен
Dehli9 Тоска
На земле Брайан Эно
Джаз
Madar Ян Гарбарк
Эти горячие Пятерки и Семерки Луис Армстронг & The Hot Five

Если вы хотите только альбомы на IPod, а не все альбомов в библиотеке ITunes, то дополнительное условие должно быть добавлено к внутреннему наиболее для-каждому, так что она будет выглядеть так:

<xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
        [string[preceding-sibling::key[1]='Genre']=$genre]
        [not(true[preceding-sibling::key[1]='Disabled'])][1]">

Добавление времени трека

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

<xsl:template name="iTunesTimeAlbum">
  <xsl:variable name="tracksInAlbum"
      select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])"/>
  <xsl:variable name="t"
      select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time'])"/>
  <xsl:call-template name="formatTime">
    <xsl:with-param name="t" select="$t"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="formatTime">
  <xsl:param name="t"/>
  <xsl:if test="$t != 0">
    <xsl:variable name="h" select="floor(($t div (1000*60*60)))"/>
    <xsl:variable name="m" select="floor(($t div (1000*60)) mod 60)"/>
    <xsl:variable name="s" select="floor(($t div 1000) mod 60)"/>
    <xsl:if test="$h != 0"><xsl:value-of select="$h"/>h</xsl:if>
    <xsl:value-of select="format-number($m,'00')"/>m
    <xsl:value-of select="format-number($s,'00')"/>s
  </xsl:if>
</xsl:template>

Опять же, если вы хотите увидеть продолжительность на IPOD, а не в библиотеке ITunes (если только некоторые треки на альбоме были выбраны для передачи на Айпод), дополнительное условие должно быть добавлено для выбора для переменного t:

<xsl:variable name="t"
      select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time']
      [not(../true[preceding-sibling::key[1]='Disabled'])])"/>

Подобный шаблон даст общее время музыки в библиотеке ITunes (или на Айпод):

<xsl:template name="iTunesTimeTotal">
  <xsl:variable name="t"
      select="sum(dict/integer[preceding-sibling::key[1]='Total Time'])"/>
  <xsl:call-template name="formatTime">
    <xsl:with-param name="t" select="$t"/>
  </xsl:call-template>
</xsl:template>

И если вы хотите иметь общий размер диска песен, он доступен против Size key:

<xsl:template name="iTunesSizeTotal">
  <xsl:variable name="s" select="sum(dict/integer[preceding-sibling::key[1]='Size'])"/>
  <xsl:value-of select="floor($s div (1000*1000)) div 1000"/>GB
</xsl:template>

Открытие листинга непосредственно в браузере

Вместо того чтобы использовать специальные инструменты, XML / XSLT, я открываю список непосредственно в браузере. Для этого я создаю «обертку» файл XML, который определяет, какие таблицы стилей, чтобы применить к какому файлу XML, используя кнопку <?xml-stylesheet> инструкции по <incl> элемента:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="albumList.xsl" type="text/xsl"?>
<wrapper>
  <incl file="iTunes Music Library.xml"/>
</wrapper>

Затем я поставил шаблон в верхней части XSL таблицы стилей, которая соответствует элементу <wrapper>  я положил вокруг включаемого файла XML, и применяю шаблоны стилей для включаемого файла XML.

<xsl:template match="/wrapper">
    <xsl:apply-templates select="document(incl/@file)"/>
  </xsl:template>

Это должно работать в любом текущем браузере; Я проверил это на Internet Explorer (6.0+) и Firefox.

Примечание: альтернативный подход был бы предварительно обработать в п-список XML в более традиционную структуру, как объяснено в www.xmldatabases.org/WK/blog/1086?t=item , который затем будет проще манипулировать с помощью XSLT , Я готов жить с preceding-sibling  контсрукции  для того , чтобы иметь возможность генерировать список в одном шаге.


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

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


Чтобы использовать этот сценарий, в своей основной или полной форме, сохранить albumList.xml и albumList.xsl показано ниже вашей Музыка / ITunes папку, и откройте albumList.xml в вашем браузере (IE6 или Firefox). Если вы хотите , чтобы адаптировать макет, с руководящими принципами выше , вы должны иметь возможность смешивать и сочетать компоненты по мере необходимости. Вы можете повторно использовать эти сценарии [без каких – либо гарантий явных или подразумеваемых] для личного использования

Файл albumList.xml (указывает , применять albumList.xsl к ITunes Music Library.xml ):

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="albumList.xsl" type="text/xsl"?>
<wrapper>
  <incl file="iTunes Music Library.xml"/>
</wrapper>

Файл albumList.xsl базовой версии (списки имя & группа альбомов на Айпод):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <!-- (c) Chris Veness 2005 -->
  <xsl:output method="html" encoding="UTF-8" indent="yes"/>

  <!-- match the wrapper and apply templates to the <incl> xml file -->
  <xsl:template match="/wrapper">
    <xsl:apply-templates select="document(incl/@file)/plist/dict/dict"/>
  </xsl:template>


  <xsl:key name="songsByGenre" match="dict" use="string[preceding-sibling::key[1]='Genre']"/>
  <xsl:key name="songsByAlbum" match="dict" use="string[preceding-sibling::key[1]='Album']"/>


  <xsl:template match="dict">
    <html>
      <head>
        <title>iPod Album Listing</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
      </head>
      <body>
        <table>

          <xsl:for-each select="dict[generate-id(.)=generate-id(key('songsByGenre',string)[1])]">
            <xsl:sort select="string[preceding-sibling::key[1]='Genre']"/>
            <xsl:for-each select="key('songsByGenre',string)[1]">
              <xsl:call-template name="albumsInGenre">
                <xsl:with-param name="genre" select="string[preceding-sibling::key[1]='Genre']"/>
              </xsl:call-template>
            </xsl:for-each>
          </xsl:for-each>

        </table>
      </body>
    </html>
  </xsl:template>


  <xsl:template name="albumsInGenre">
    <xsl:param name="genre"/>

    <!-- genre header -->
    <tr><td colspan='3'><b><xsl:value-of select="$genre"/></b></td></tr>

    <!-- output each album in genre -->
    <xsl:variable name="song" select="/plist/dict/dict/dict"/>
    <xsl:for-each select="$song[generate-id(.)=
        generate-id(key('songsByAlbum',string[preceding-sibling::key[1]='Album'])[1])]">
      <xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
      <xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
          [string[preceding-sibling::key[1]='Genre']=$genre]
          [not(true[preceding-sibling::key[1]='Disabled'])][1]">
        <tr valign='top'>
          <td width='20'> </td>
          <!-- the album name: -->
          <td><xsl:value-of select="string[preceding-sibling::key[1]='Album']"/></td>
          <!-- the artist: -->
          <td>
            <xsl:choose>
              <xsl:when test="true[preceding-sibling::key[1]='Compilation']">
                <i>Compilation</i>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/>
              </xsl:otherwise>
            </xsl:choose>
          </td>
        </tr>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

Файл albumList.xsl полной версии (включает в себя полную библиотеку ITunes с раз и итогами):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <!-- (c) Chris Veness 2005-2006 -->
  <xsl:output method="html" encoding="UTF-8" indent="yes"/>


  <!-- match the wrapper and apply templates to the <incl> xml file -->
  <xsl:template match="/wrapper">
    <xsl:apply-templates select="document(incl/@file)/plist/dict/dict"/>
  </xsl:template>


  <xsl:key name="songsByGenre" match="dict" use="string[preceding-sibling::key[1]='Genre']"/>
  <xsl:key name="songsByAlbum" match="dict" use="string[preceding-sibling::key[1]='Album']"/>


  <xsl:template match="dict">
    <html>
      <head>
        <title>iTunes Album Listing</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <style type='text/css'> td { vertical-align: top; padding-right: 1em; } </style>
      </head>
      <body>
        <table>

          <xsl:for-each select="dict[generate-id(.)=generate-id(key('songsByGenre',string)[1])]">
            <xsl:sort select="string[preceding-sibling::key[1]='Genre']"/>
            <xsl:for-each select="key('songsByGenre',string)[1]">
              <xsl:call-template name="albumsInGenre">
                <xsl:with-param name="genre" select="string[preceding-sibling::key[1]='Genre']"/>
              </xsl:call-template>
            </xsl:for-each>
          </xsl:for-each>

          <!-- totals -->
          <tr>
            <td colspan='4' style='color: gray'><b>Total</b></td>
            <td style='color: gray' align='right'><xsl:call-template name="iPodTimeTotal"/></td>
            <td style='color: gray' align='right'><xsl:call-template name="iTunesTimeTotal"/></td>
          </tr>
          <tr>
            <td colspan='4'> </td>
            <td style='color: gray' align='right'><xsl:call-template name="iPodSizeTotal"/></td>
            <td style='color: gray' align='right'><xsl:call-template name="iTunesSizeTotal"/></td>
          </tr>

        </table>
      </body>
    </html>
  </xsl:template>


  <xsl:template name="albumsInGenre">
    <xsl:param name="genre"/>

    <tr>  <!-- genre header -->
      <td colspan='4'><b><xsl:value-of select="$genre"/></b></td>
      <td align='right' style='color: gray'><i>iPod</i></td>
      <td align='right' style='color: gray'><i>iTunes</i></td>
    </tr>

    <xsl:variable name="song" select="/plist/dict/dict/dict"/>
    <xsl:for-each select="$song[generate-id(.)=
        generate-id(key('songsByAlbum',string[preceding-sibling::key[1]='Album'])[1])]">
      <xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
      <xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
          [string[preceding-sibling::key[1]='Genre']=$genre]
          [1]">
          <!--  for albums on iPod only, add
                [not(true[preceding-sibling::key[1]='Disabled'])] -->
        <tr>
          <td> </td>
          <td><xsl:call-template name="album"/></td>
          <td><xsl:call-template name="artist"/></td>
          <td align='right'><xsl:call-template name="iPodTimeAlbum"/></td>
          <td align='right'><xsl:call-template name="iTunesTimeAlbum"/></td>
        </tr>
      </xsl:for-each>
    </xsl:for-each>
    <tr><td colspan='6'>&#160;</td></tr>  <!-- space between genres -->
  </xsl:template>


  <xsl:template name="album">
    <xsl:value-of select="string[preceding-sibling::key[1]='Album']"/>
  </xsl:template>


  <xsl:template name="artist">
    <xsl:choose>
      <xsl:when test="true[preceding-sibling::key[1]='Compilation']">
        <i>Compilation</i>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <xsl:template name="iPodTimeAlbum">
    <xsl:variable name="tracksInAlbum"
        select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])"/>
    <xsl:variable name="t"
        select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time']
            [not(../true[preceding-sibling::key[1]='Disabled'])])"/>
    <xsl:call-template name="formatTime">
      <xsl:with-param name="t" select="$t"/>
    </xsl:call-template>
  </xsl:template>


  <xsl:template name="iTunesTimeAlbum">
    <xsl:variable name="tracksInAlbum"
        select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])"/>
    <xsl:variable name="t"
        select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time'])"/>
    <xsl:call-template name="formatTime">
      <xsl:with-param name="t" select="$t"/>
    </xsl:call-template>
  </xsl:template>


  <xsl:template name="iPodTimeTotal">
    <xsl:variable name="t" select="sum(dict/integer[preceding-sibling::key[1]='Total Time']
        [not(../true[preceding-sibling::key[1]='Disabled'])])"/>
    <xsl:call-template name="formatTime">
      <xsl:with-param name="t" select="$t"/>
    </xsl:call-template>
  </xsl:template>


  <xsl:template name="iTunesTimeTotal">
    <xsl:variable name="t" select="sum(dict/integer[preceding-sibling::key[1]='Total Time'])"/>
    <xsl:call-template name="formatTime">
      <xsl:with-param name="t" select="$t"/>
    </xsl:call-template>
  </xsl:template>


  <xsl:template name="iPodSizeTotal">
    <xsl:variable name="s" select="sum(dict/integer[preceding-sibling::key[1]='Size']
        [not(../true[preceding-sibling::key[1]='Disabled'])])"/>
    <xsl:value-of select="floor($s div (1000000)) div 1000"/>GB
  </xsl:template>


  <xsl:template name="iTunesSizeTotal">
    <xsl:variable name="s" select="sum(dict/integer[preceding-sibling::key[1]='Size'])"/>
    <xsl:value-of select="floor($s div (1000000)) div 1000"/>GB
  </xsl:template>


  <xsl:template name="formatTime">
    <xsl:param name="t"/>
    <xsl:if test="$t != 0">
      <xsl:variable name="h" select="floor(($t div (1000*60*60)))"/>
      <xsl:variable name="m" select="floor(($t div (1000*60)) mod 60)"/>
      <xsl:variable name="s" select="floor(($t div 1000) mod 60)"/>
      <xsl:if test="$h != 0"><xsl:value-of select="$h"/>:</xsl:if>
      <xsl:value-of select="format-number($m,'00')"/>:<xsl:value-of select="format-number($s,'00')"/>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

Ссылка на оригинал статьи: http://www.movable-type.co.uk/scripts/itunes-albumlist.html

Серийные номера и номера бюро военных кораблей ВМФ США и США морской пехоты – с 1911 года по настоящее время

Original:http://www.joebaugher.com/navy_serials/navyserials.html

Военно-морской флот Соединенных Штатов приобрел свой первый самолет в 1911 году, плавучий плот Curtiss Triad. Первоначально ВМС США последовательно присваивали серийные номера самолетам своих изготовителей, причем это отдельная последовательность номеров для каждого производителя. Серийный номер состоял из двух частей. Первая часть была буквенной, которое обозначало изготовителя – A для Curtiss, B для Wright и т. д. За буквой следовал номер, чтобы показать последовательность закупок от каждого производителя. Например, первый самолет ВМФ, построенный на Кёртиссе, был- А-1, второй А-2 и т. д.

Система должна была быстро адаптироваться к различным типам самолетов, полученным от одного и того же производителя – для того, чтобы отличить летающие лодки от понтонных гидросамолетов, Кертисс должен был получить еще одну букву «С», а буква D – Берджессу и Кертису (нет взаимосвязи), а E был отнесен к земноводным Кертисса.

В марте 1914 года эта система обозначения, основанная на изготовителе, была оставлена ​​и была заменена двухбуквенной схемой классификации типов и подтипов. Первой буквой был тип или класс – А означало «Тяжелее воздуха», «В» для «Свободного воздушного шара», «С для дирижабля» и «D» для воздушного шара. Вторая буква была использована для обозначения подтипа – например, AH был гидросамолетом, AB был летающей лодкой, а AX был амфибией. Все оставшиеся в живых самолеты, приобретенные по первоначальной схеме, были переименованы и перерегистрированы. Каждой классификации типов / подтипов присваивалась отдельная последовательность серий.

В мае 1917 года, во время вступления США в WW1, это было изменено на последовательный числовой список, независимо от типа. По какой-то причине число 51 было взято в качестве удобной отправной точки. Старые префиксные буквы были сохранены в течение короткого времени, но больше не имели никакого отношения к серийным номерам. 19 мая 1917 года префиксные буквы были официально отменены и заменены одной буквой A для Airplane. Эти номера первоначально назывались «номерами строений», но позднее их называли «номерами для обозначения». В последующие годы они стали известны как Бюро Номеров (BuNos), так как они были назначены Бюро аэронавтики ВМС после того, как эта организация была создана в 1921 году. Префикс A был удален из номеров в конце 1930 финансового года (после OJ2, A-9204).

Первоначальная последовательность достигла 9999 в 1935 году, и вместо того, чтобы расширять серийный номер до пяти цифр, новая последовательность чисел была начата в 0001. Это так называемая вторая серия номеров Бюро.

В 1940 году было заказано так много самолетов в результате программы перевооружения президента Франклина Рузвельта, что было установлено, что необходимо прекратить работу второй серии на 7303, чтобы избежать путаницы с самолетами, имеющими последние цифры в первоначальной серии, которые все еще были в эксплуатации. Третья (и окончательная) серия номеров Бюро была запущена с 00001 (с использованием 5 цифр с начала). Когда в 1945 году третья серия достигла 99999, ей было разрешено продолжать работу в шесть цифр. Эта серия чисел продолжается и поныне. Сейчас она достигла 165000.

Корпуса морской пехоты закупаются военно-морским флотом, поэтому они используют номера Бюро Военно-Морского Флота, но Береговая охрана является частью Департамента внутренней безопасности США (в мирное время) и использует свою последовательность порядковых номеров.

Номер Бюро присваивается воздушному судну, когда он первоначально был заказан, а не когда он фактически доставлен Военно-Морскому Флоту. Общее количество присвоенных серийных номеров (к настоящему времени более 165000) не отражает фактическое количество поставленных самолетов из-за крупномасштабных аннулирования контрактов в конце Второй мировой войны и других изменений в программе за последние годы.

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

Военно-воздушные силы США имеют совершенно другую схему серийных номеров, основанную на закупках самолетов в течение каждого финансового года. Иногда воздушные суда переводятся из ВВС США во флот. Если перенос предполагается постоянным, то обычно передаваемому самолету присваиваются совершенно новые номера ВМФ. Однако, если ожидается, что передача будет носить временный характер, оригинальные серийные номера ВВС США часто сохраняются в службе ВМФ, но иногда случается так, что на самолетах, предоставленных Военно-Морскому Флоту, присваиваются совершенно новые номера бюро. К сожалению, система не всегда последовательна.

Существует несколько основных исключений при присвоении номеров в шестизначной системе нумерации. В 1960-х годах существовал блок шестизначных чисел, начинающихся с 00, которые были присвоены противолодочному вертолету-беспилотнику, известному как QH-50C и QH-50D. Причина этой нечетной системы, похоже, потеряна в истории. Другим важным исключением является набор не последовательных номеров, начинающихся с 198003 года и колеблющихся до 999794. Эти номера обычно присваивались самолетам, которые поступали в военно-морской флот от ВВС, армии или даже от иностранных организаций. Кажется, что нет никаких рифм или причин для этих назначений – во многих случаях они были получены путем изменения системы нумерации воздушных судов ВВС. В других случаях они были построены по номерам изготовителя. Например, морской пехотинец F-21A, который был арендован у Израиля в 1987 году для несходной боевой подготовки в воздухе, получил номера бюро, полученные из трехзначного номера конструкции самолета с префиксом 999.

Производственные блоки

В первые послевоенные годы, ВВС США, ВМС США и Корпуса морской пехоты часто использовали систему производственного блока для отслеживания незначительных изменений производственной линии, которые не были сочтены достаточно решительными, чтобы вызвать новый порядковый номер конфигурации самолета. Эта система продолжалась после принятия единой системы обозначения в 1962 году. Как и ВВС, военно-морской флот / морской пехотинец не использовал обозначения производственного блока для всех своих самолетов, и в системах, используемых с одного типа воздушного судна другому.

Номера блоков обычно прогрессируют с шагом 5, начиная с -1, затем -5, -10 и т. д. Промежуточные числа были зарезервированы для обозначения модификаций поля, выполняемых после доставки воздушного судна, хотя их использование, по-видимому, является исключительным для ВВС США, и нет никаких известных записей о каких-либо ВСУ, имеющих такие промежуточные номера. Исключения из правила «плюс 5» были довольно частыми, главными примерами были McDonnell Banshee, Demon и Phantom и LTV Corsair II, чьи номера блоков прогрессировали с единичными приращениями -1. -2, -3 и так далее.

В дополнение к номерам блоков. Военно-Морской Флот также часто использовал Block Letters для обозначения различных стандартов производства. Хотя они, кажется, не связаны с каким-либо обозначением в стиле USAF. Были различные стили письма и комбинация букв, которые были использованы. Разные стили, по-видимому, не имеют особого значения и, вероятно, существуют из-за отсутствия какой-либо твердой директивы USN по этому вопросу. Иногда последовательность начиналась с буквы «A» или «a», при этом первое изменение в стандарте производства обозначалось как «B», затем «C» и т. Д., До достижения «Z». Если буквы за пределами «Z» были Иногда случалось, что буквы начинались с «А», но в других случаях следующее изменение обозначалось «АА» на «ZZ». Чтобы избежать путаницы с нулевым числом, буква «О» является Пропущено.

Во флоте эти блок-буквы или номера были прикреплены к номеру бюро, а не прикреплены к официальному обозначению, как это практикуется в ВВС США. Однако, в отличие от ВВС США, Блок-письмо или Номер чаще всего использовались исключительно в официальных отчетах и ​​очень редко наносились на самолеты. Когда на самолете появляются буквенные буквы или цифры, они обычно отображаются в виде суффикса к полному шестизначному BuNo, который появляется либо на задней части фюзеляжа, либо на ребрах, причем буква или номер появляются меньшими символами, чем сам BuNo.

Буквы в формате Modex и боковые номера

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

Есть некоторые споры относительно происхождения названия “modex”. Кажется, что одна из возможностей такова. Когда военно-морские самолеты летят в своих контролируемых районах, они идентифицируются по их «позывному сигналу» – «Нугграсс-122», «Тигрэйл-012», «Черный орел 601», «Лима-виски-05» и т. д. Однако в контролируемом гражданским воздушным пространством они не отвечают стандартам контроля воздушного движения. Таким образом, вместо этого, эти военно-морские самолеты идентифицируются по ВМФ и последним четырем цифрам BuNo. Кроме того, приемоответчик идентифицирует (или «Squawks») самолет на экране радара таким же образом. Поскольку существуют различные «Режимы», используемые системой управления воздушным движением, мы получаем имя MODEX, плюс последние четыре цифры BuNo.

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

Согласно одному из моих источников, цифры в числах сбоку за первой находятся в восьмеричном формате (цифры идут от 1 до 7, затем от 10 до 17, от 20 до 27 и т. д.), причем цифры 8 или 9 никогда не используются. Это было сделано, по-видимому, потому, что действия по техническому обслуживанию первоначально записывались на перфокартах и ​​должны были обрабатываться электронными учетными машинами IBM и компьютерами, которые могли обрабатывать восьмеричные числа. Любопытно, что число сторон остается в восьмеричном формате и по сей день, хотя компьютерные системы с тех пор были модернизированы во много раз. Однако я видел номера сторон за первой цифрой, которые действительно имеют 8 или 9, так что это ограничение не должно быть универсальным.

Другим возможным объяснением происхождения восьмеричной системы бокового числа является характер ранних систем ИФФ (Идентификация друга или врага). С прибытием раннего военно-воздушного самолета В-2А ВМС численность бортов изменилась с нумерации от базовой – 10 до 8 (например, 500, 501, 502, …, 507, 510, 511 и т. Д.). Автоматическая система слежения E-2As потребовала такого изменения, поскольку ее компьютеры могли работать только с цифрами с восьмью основными точками. IFF используется контроллерами для «положительного контроля». Существует несколько режимов: два введенных пилотом по направлению контроллера, один для высоты сквоч-сигнала и один для военного использования. Ранние транспондеры устанавливались позиционированием переключателей вкл. или выкл. с четырьмя столбцами из 3 переключателей для кода 4096 или двух столбцов из трех для 64-кода. 4096 – это количество различных четырехзначных чисел, которые могут быть созданы без использования 8 или 9 и в том числе 0000, которые никогда не должны использоваться транспондерами самолетов. В такой схеме 12 двоичных чисел. IFF может обрабатывать только три бинарных места, поэтому 8 и 9 не используются. Системы IFF в то время (и я думаю, что они все еще делают) использовали восьмеричную систему, а самый высокий «squawk» в режиме 2 был 7777, режим 1 и 3 – 77. Следовательно, появление восьмеричной системы нумерации на самолетах. Несомненно, существует несколько причин, по которым используется восьмеричное, а не десятичное, с одной стороны, оно точно отражает базовую «бито-ориентированную» природу кодов. Если бы десятичные знаки использовались, тогда для режима «A» (гражданский, «военный» 3) были бы полезными только числа от 0 до 4096, которые, вероятно, труднее понять, чем возможность использовать любое 4-значное число (0000-7777). Кроме того, в предыдущем военном режиме (режим «1») разрешены только 6-битовые коды (00-77), упрощенность повышалась, если считать удвоение количества цифр, чем если бы это был случай внезапного разрешения использовать Числа в диапазоне от 64 до 4096. Последнее дополнение к радиолокационной технологии, Mode-S, расширяет коды squawk с 12 бит до 24 бит, что позволяет постоянно присваивать коды отдельным самолетам без дублирования. Однако, несмотря на недавнее изобретение, эти коды по-прежнему представлены с использованием восьмеричной (в виде 8 цифр) или шестнадцатеричной (в виде 6 цифр / букв).

Ниже приведена схема бортовых номеров для крыльев воздушных судов-перевозчиков. Как правило, первая цифра обозначает тип воздушного судна, а оставшиеся две цифры представляют отдельные самолеты внутри конкретного крыла. Истребители-эскадрильи на базе перевозчика обычно имеют трехзначные боковые номера 1XX или 2XX (оба набора чисел используются, если в несущем крыле имеются две истребительные эскадрильи). Номера, начинающиеся с 1, окрашены в красный цвет, а цифры, начинающиеся с 2, окрашены в желтый цвет. Обычно самолет самолета эскадрильи имеет номер 101 или 201, самолет исполнительного чиновника 102 или 202 и последующие самолеты, пронумерованные в порядке старшинства пилотов. Иногда, 100 или 200 используется для представления плоскости КАГ (Командующего Авиагруппы), если таковая имеется. Я даже слышал о бортовом номере 000, который якобы был применен к самолету адмирала. Световые самолеты имеют номера, начинающиеся с 3 (светло-зеленые) или 4 (средние синие). У тяжелых ударных самолетов цифры начинаются с 5, которые окрашены в темно-зеленый цвет. Самолеты с неподвижным крылом, принадлежащие эскадронам VAW, имеют номера 60X, которые окрашены в темно-бордовый цвет, хотя они используются довольно редко. В эскадронах VAQ использовались цифры 61X, которые были окрашены в темно-синий цвет, но это было изменено несколько лет назад до 5XX, обычно начиная с 500. Цвет обычно черный, за исключением самолетов CAG, которые могут быть практически любого цвета. VS эскадроны используют цифры 62X и 63X, с голубым или темно-красным цветом, но эскадрильи S-3 также использовали бортовые числа 70X или 71X с сплошным черным цветом. Вертолетные эскадрильи используют цифры 70X или 71X с зеленым цветом. Некоторые источники утверждают, что 3xx, 8xx и 9xx зарезервированы для групп пополнения флота (RAGs), но это не всегда так, поскольку, по крайней мере, одна эскадрилья света A-7 использовала 3xx.

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

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

Наземные военно-морские самолеты также используют бортовые номера, но это, как правило, последние три цифры BuNo. Менее предсказуемыми были бортовые номера, присвоенные испытательному центру, аэродрому и судам. Однако, у судовых самолетов обычно есть бортовые числа, которые являются числом корпуса судна. Например, когда перевозчику USS Джону Ф. Кеннеди (CV-67) был присвоен C-1, у самолета в качестве бортового номера было «67».

Я был бы рад услышать от любого, кто имеет какие-либо дополнения или исправления к этим номерам и номерам сторон.

Свалка авиационной техники

Окончательный конец для многих самолетов и вертолетов военно-морского флота и морской пехоты, как только они покинут активную службу, – свалка авиационной техники в Аризоне. Сухой климат и щелочная почва региона делают его идеальным для открытого хранения самолетов. В конце Второй мировой войны многие излишки самолетов ВМФ были сохранены в NAS Litchfield Park, примерно в 30 милях к западу от Феникса, штат Аризона. После 1967 года этот объект был закрыт, и военно-морской флот перевел операцию на авиабазу Дэвис-Медан в районе Тусона, штат Аризона. Самолеты сверхмощной обороны и береговой охраны хранятся там после их снятия с эксплуатации. Иногда самолеты фактически возвращаются на активную службу, либо в качестве беспилотных летательных аппаратов с дистанционным управлением, либо продаются дружественным иностранным правительствам, но чаще всего их убирают для запасных частей, чтобы удерживать другие летательные аппараты в полете или утилизируют.

Изначально это место было известно, как военный центр хранения и утилизации воздушных судов (MASDC), и в октябре 1985 года оно было изменено на Центр аэрокосмического обслуживания и регенерации (AMARC). AMARC был официально переименован 2 мая 2007 года в качестве 309-й группы по аэрокосмическому обслуживанию и регенерации (AMARG), но по-прежнему использует название AMARC для всемирного признания и сохранения наследия. Если я знаю дату, когда самолет был передан MASDC / AMARC, я перечисляю ее здесь.

Когда самолет попадает на AMARG, ему присваивается кодовый номер (известный как контрольный номер производства или PCN), состоящий из четырех букв, за которым следует трехзначное число. В первых двух письмах указывалась служба (AA для ВВС, AN для военно-морского флота, AC для береговой охраны, AX для правительственных агентских самолетов, AY для иностранных союзных самолетов). Вторая пара букв указывала тип воздушного судна (например, 3A для самолета A-4 Skyhawk), а трехзначное число указывает порядок, в котором конкретная плоскость этого типа была введена в AMARG. Например, первый A-4, допущенный к AMARC, будет пронумерован AN3A001, с двумя нулями, добавленными, чтобы подсказать количество цифр до 3. Таким образом, PCN был полезен при кратковременном сообщении, кто владеет самолетом, какой тип самолета он Был, и порядок, в котором он достиг AMARG.

До октября 1994 года номер в коде PCN имел три цифры, но AMARC понял, что вскоре они будут иметь более 1000 F-4 на инвентаре, и было принято решение о необходимости расширения формата числа до четырех цифр Чтобы приспособить новых Призрачных прибытий. Я предполагаю, что как только AMARC изменил свое поле базы данных, чтобы использовать 6 символов, они решили использовать этот стиль для ВСЕХ новых прибытий с октября 1994 года, а нуль был префикс, когда номер заказа был меньше 1000. Ref: eLaReF, Jun 17, 2012.

Чтобы добавить путаницы, один и тот же самолет мог иметь несколько PCN. Например, если самолет в хранилище в AMARG возвращается к обслуживанию, он получит новый PCN, когда он будет возвращен AMARG для хранения во второй раз. Воздушному судну также может быть назначен другой PCN, если он административно перенаправлен на другую услугу. Например, AMARG в настоящее время хранит C-131, который первоначально прибыл как военно-морской ресурс (и ему был присвоен военно-морской флот PCN). Военно-морской флот передал самолет в ВВС (поэтому военно-морской флот был удален и заменен ВВС ВВС). Затем USAF передал его другому правительственному агентству, поэтому PCN USAF был удален и заменен агентством USN Gov’t PCN, начиная с префикса «AX». Тот же самолет, три разных PCN. (Ссылка: Роберт Д. Рейн, 27 июня 2013 г.)

В дополнение к воздушным судам, которые передаются между службами, воздушное судно могло получать несколько PCN, если оно возвращалось на объект несколько раз, например, – самолет мог прийти в AMARG для продления срока службы (ему был бы предоставлен PCN для Продолжительность его повторной установки). Тогда он был бы возвращен оперативному флоту. Во время обслуживания, если «операторы» определяют, что все воздушные суда этого типа нуждаются в чем-то еще, чтобы их проверить, самолет вернется к 309 AMARG для этой проверки в рамках некоторых незначительных ремонтных работ. По прибытии он получил бы новый (2-й) PCN. По завершении мелкого ремонта самолет снова вернется к операторам. В конце концов, когда операторы определяют, что воздушное судно больше не требуется, и удаляют его на хранение, третий PCN был бы назначен. (Ссылка: Роберт Д. Рейн, 27 июня 2013 г.)

Недавно AMARG представила новую компьютерную систему и решила прекратить назначение PCN, когда самолет прибывает на объект. Теперь все сделано по серийному номеру, так как ни один из двух самолетов не имеет точно такого же серийного номера. ПХН не удалялись со старых самолетов, но новые ПХН больше не назначались воздушным судам по прибытии. (Ссылка: Роберт Д. Рейн, 27 июня 2013 г.) Список военных самолетов, переданных MASDC / AMARC, можно найти на сайте www.amarcexperience.com.

Серийные номера изготовителя

Когда самолет построен, компания, которая его построила, присваивает ему заводской номер. Это число обычно отображается на табличке, установленной где-то внутри самолета. Когда самолет продается Военно-Морскому Флоту или Корпусу морской пехоты, Министерству обороны выдается номер бюро (это военный серийный номер). Эти два числа не связаны друг с другом, но часто путают друг с другом. Когда я знаю серийный номер изготовителя конкретного военного самолета, я перечисляю его. Если военный самолет в конечном итоге попадает в гражданские руки, ему выдается гражданский регистрационный номер национальным органом гражданской авиации владельца. В США эти номера выданы FAA и известны как N-номера в США, так как все они начинаются с буквы N. Обычно FAA использует серийный номер изготовителя воздушного судна для отслеживания этих самолетов. Например, многие военно-транспортные самолеты R4D оказались в гражданских руках после того, как их военная служба закончилась, и их отслеживают, используя серийные номера их изготовителя.

История конкретного самолета

Есть много людей, которые хотят знать об истории операций или окончательном решении конкретного самолета ВМС или Корпуса морской пехоты, упомянутого в этой базе данных, но о котором у меня мало информации или нет вовсе. Если у вас есть конкретный вопрос об истории конкретного самолета ВМС, вы можете попробовать зайти в Военно-исторический центр, который расположен в Вашингтоне, округ Колумбия. У них есть карты практически всех самолетов, когда-либо принадлежавших или управляемых флотом, и они могли бы ответить на ваш вопрос довольно быстро. Другим источником является архив картотеки истории воздушных судов, который ведет Национальный архив аэрокосмических музеев, в котором хранятся микрофильмированные копии записей воздушных судов, созданных ВМС США. Они также могут вам помочь. Тем не менее, вы всегда можете написать мне по электронной почте в любом случае, и я посмотрю, смогу ли я что-нибудь откопать.