четверг, 13 мая 2010 г.

Совместная работа над кодом в компании Google

Во второй главе книги «Coders at Work», Брэд Фицпатрик (Brad Fitzpatrick) — автор Live Journal, а сейчас сотрудник компании Google, помимо всяких интересных баек о создании Live Journal, об учебе и о многом другом, рассказывает и о принципах владения кодом и о совместной работе над ним в компании Google.

SharedSources

Как известно, в Google существует возможность использовать двадцать процентов своего рабочего времени в целях, отличных от целей текущего проекта (но в целях и интересах компании в целом). Это явление называется групплеты (grouplet) (об этом можно почитать в замечательной статье «The Google Way: Give Engineers Room», или в переводе этой статьи здесь), соответственно, у каждого разработчика может появиться дикое желание порыться в чужом коде и поучаствовать в каком-то проекте. А поскольку таких проектов, мягко говоря, много, то требуются некоторые формальные правила, которые позволят поддерживать весь код в актуальном состоянии и не позволят его качеству опускаться ниже определенного уровня.

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

Для того, чтобы исправленный код попал обратно в репозиторий должны быть выполнены два требования. Во-первых, вы должны получить «одобрение» от владельца кода (code owner), а во-вторых, одобрение от сертифицированного специалисти по тому языку программирования, который используется в этом проекте (readability approved person) (кстати, совершенно не обязательно, чтобы это были два разных человека, две эти роли вполне могут ужиться и в одном человеке).

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

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

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

Кстати, а как обстоят дела дела в вашей компании с владением кода и совместной работой над ним?

Дополнительные ссылки:
Code readability

вторник, 11 мая 2010 г.

Проектирование по контракту. Утверждения

Утверждения

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

Спецификация и реализация неразрывно связаны друг с другом; спецификация говорит о том, что должна делать система, а реализация определяет как это будет достигнуто. Оба эти аспекта программного продукта должны развиваться одновременно, чего в большинстве программных проектов не происходит. (Хотя, на самом деле, далеко не во всех проектах спецификация вообще существует в каком-либо формальном виде, в таком случае единственным источником спецификации является исходный код, что в свою очередь делает невозможным проверить его корректность.) В случае когда спецификация и реализация находятся в разных источниках мы сталкиваемся с классической проблемой дублирования информации и в этом случае рассогласование этой информации является всего лишь вопросом времени. В проектировании по контракту выражение спецификации осуществляется с помощью механизма утверждений (assertions).

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

Утверждение – это логическое выражение, которое должно быть истинным на некотором участке программы и может включать сущности нашего ПО. Утверждениями могут служить обычные булевы выражения с некоторыми расширениями. Так, в утверждениях помимо булевых выражений могут применяться функции (но с некоторыми ограничениями: это должны быть функции без “побочных эффектов”, т.е. не изменяющие состояние объекта). А для постусловий необходима возможность обратиться к результату выполнения функции, а также к значению, которое было до начала выполнения этой функции (определяется термином “old”).

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

ПРИМЕЧАНИЕ
Первым защитником использования утверждений в программировании был никто иной, как сам Алан Тьюринг. На конференции в Кембридже 24 июля 1950 г. он представил небольшой доклад “Проверка больших программ”, в которой объяснял эту идею с большой ясностью. “Как можно проверить большую программу, утверждая, что она правильна? Чтобы для проверяющего задача не была слишком трудной, программист обязан написать некоторые утверждения, которые можно проверить индивидуально, и из которых корректность программы следует достаточно просто” [Hoare 1981]

Предусловия и постусловия

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

Пусть предусловие определяется ключевым словом require, а постусловие – ключевым словом ensure. Тогда, если с некоторой функцией r связаны утверждения require pre и ensure post, то класс говорит своим клиентам следующее [Meyer2005]:

“Если вы обещаете вызвать r в состоянии, удовлетворяющем pre, то я обещаю в заключительном состоянии выполнить post”.

{Pre r} R {Post r}

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

//Math.cs

public class Math {

    public static double Sqrt(double x) {

        Contract.Requires(x >= 0, "Positive x");

        // Реализация метода

    }

}

 

//Stack.cs

public class Stack<T> {

    public void Push(T t) {

        Contract.Requires(t != null, "t not null");

        Contract.Ensures(Count == Contract.OldValue(Count) + 1,

                         "One more item");

        // Реализация метода

    }

 

    public T Pop() {

        Contract.Requires(Count != 0, "Not empty");

        Contract.Ensures(Contract.Result<T>() != null,

                         "Result not null");

        Contract.Ensures(Count == Contract.OldValue(Count) - 1,

                         "One fewer item");

        // Реализация метода

    }

 

    public int Count {get;}

}

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

Предусловие связывает вызывающий код: определяются условия при которых вызов программы клиентом легитимен (например, x > 0 для функции Sqrt или Count != 0 для функции Pop класса Stack). При этом обязательства клиента приносят выгоду классу-поставщику, поскольку классу, выполняющему операцию, не нужно заботиться о том, что же делать при нарушении предусловия: возвращать значение по умолчанию или код ошибки, генерировать исключение, сохранять информацию об ошибки в поток ввода-вывода или прерывать выполнение программы.
Постусловие связывает класс: определяются условия, которые должны быть выполнены по завершению операции (класс Stack должен обеспечить увеличение количество элементов на 1 после выполнения функции Push). Здесь выгода клиента (результат выполнения функции) оборачивается обязательствами поставщика (он уже не может не выполнить свои обязательства, коль они прописаны в контракте).

Правило доступности предусловия

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

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

// Stack.cs

public class Stack<T> {

    public T Pop() {

        Contract.Requires(Count != 0, "Not empty");

        Contract.Ensures(Contract.Result<T>() != null,

                         "Result not null");

        Contract.Ensures(Count == Contract.OldValue(Count) - 1,

                         "One fewer item");

        // Реализация

    }

    private int Count {get;}

}

В этом случае клиент класса Stack не может самостоятельно удостоверится, удовлетворяет ли он предусловию или нет (поскольку у него нет доступа к проверке предусловия самостоятельно). Чтобы исключить такую проблему существует правило, согласно которому «каждый компонент, появляющийся в предусловии программы, должен быть доступен каждому клиенту, которому доступна сама программа”.

ПРИМЕЧАНИЕ
При использовании библиотеки Code Contracts приведенный выше код компилируется, но компилятор выдает предупреждение вида: warning CC1038: CodeContracts: Member 'get_Count' has less visibility than the enclosing method ' Stack`1.Pop'.

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

Инварианты класса

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

Такими свойствами могут служить внутренние условия (некоторое поле не равно null или количество элементов неотрицательно) или правила согласованности внутреннего состояния объекта (empty = (count = 0) или deposit_list.total – withdrawals_list.total = balance). Каждое такое условие не связывает конкретные функции, а характеризует объект в каждый устойчивый момент времени.

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

Утверждение Inv является корректным инвариантом класса, если и только если оно удовлетворяет следующим двум условиям [Meyer2005]:

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

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

Первое условие определяет роль функции создания в жизненном цикле объекта класса и может быть выражено формально следующим образом:

{Default and pre} body {post and Inv}

где Default – состояние объекта некоторого класса со значениями полей по умолчанию (которое зависит от конкретного языка или платформы), pre – предусловие, body – тело конструктора, post – постусловие, Inv – инвариант класса.

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

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

{Inv and pre} body {Inv and post}

где body – тело экспортируемого метода, pre – предусловие, post – постусловие, а Inv – инвариант класса.

Эта формула корректности означает, что любое выполнение метода (body), которое начинается в состоянии, удовлетворяющем инварианту (Inv) и предусловию (pre), завершится в состоянии, в котором выполняются инвариант (Inv) и постусловие (post).

Инструкция утверждения

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

При использовании рассмотренной ранее функции Sqrt предположение о неотрицательном значении аргумента может быть известно из контекста:

double x = a * a + b * b; //x не может быть отрицательным

// ...

Contract.Assert(x > 0, "because x computes as a*a + b*b");

var res = Part1.Math.Sqrt(x);

“В обычных подходах к конструированию ПО, хотя вызовы и другие операции часто основываются на корректности различных предположений, последние, чаще всего являются неявными. Разработчик уверяет себя, что некоторое свойство всегда имеет место в некоторой точке, использует этот анализ при написании кода, но после всего этого не фиксирует этого в тексте программы, в результате смысл работы теряется. Когда некто, возможно, сам автор, несколькими месяцами позже, захочет разобраться в программе, возможно, с целью ее модификации, ему придется начинать работу с нуля, поскольку все предположения остались в сознании автора. Инструкция утверждения помогает избежать подобных проблем, требуя документирования нетривиальных предположений” [Meyer2005].

ПРИМЕЧАНИЕ
В проектировании по контракту, предложенном Бертраном Мейером содержится еще один тип утверждений: инварианты и варианты циклов, которые помогают строить корректные циклы. Но поскольку этот вид утверждений большинством других реализаций принципов проектирования по контракту не поддерживается и является “тактическим”, а не “стратегическим” элементом, то в данной статье он рассматриваться не будет.

пятница, 7 мая 2010 г.

Проектирование по контракту. Корректность ПО

Введение

С момента реализации принципов проектирования по контракту в промышленном языке программирования прошло уже более десяти лет, но именно сегодня, после появления контрактов на платформе .net началось бурное обсуждение этого явления компьютерным сообществом. Но, как и у любого “популярного” явления (которое автоматически становится популярным для многих разработчиков, если за него берется столь сильный участник мира разработки программного обеспечения, как компания Майкрософт) есть и обратная сторона. В сети стало появляться множество публикаций на тему программирования по контракту, которые имеют мало общего с изначальными принципами заложенными Бертраном Мейером (автором этого принципа и языка программирования Eiffel), либо описывают лишь особенности применения конкретной реализации, при этом уделяя слишком мало внимания целям и идеям, положенным в основу проектирования по контракту (Design by Contract).

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

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

Проектирование по контракту

Проектирование по контракту (Design by Contract) – это установление отношений между классом и его клиентами в виде формального соглашения, недвусмысленно устанавливающие права и обязанности сторон. Только через точное определение для каждого модуля требований и ответственности можно надеяться на достижение существенной степени доверия к большим программным системам [Meyer2005].

Figure1

Рисунок 1 – Контракты между программными элементами

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

Корректность ПО

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

Рассмотрим более конкретный пример. Что вы можете сказать о следующей функции:

int DoSomething(int y) {

    int x = y / 2;

    return x;

}

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

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

ПРИМЕЧАНИЕ
Корректность – это согласованность программных элементов с заданной спецификацией.
Термин “корректность” не применим к программному элементу, он имеет смысл лишь для пары – “программный элемент и его спецификация”

Формула корректности. Сильные и слабые условия

Помимо неформальных определений, существует математическая нотация, широко применяемая в теории формальной проверки правильности программ.
Пусть A – это некоторая операция, тогда формула корректности (correctness formula) – это выражение вида:

{P} A {Q}

Формула корректности, называемая также триадой Хоара, говорит следующее: любое выполнение А, начинающееся в состоянии, где Р истинно, завершится и в заключительном состоянии будет истинно Q, где A обозначает операцию, P и Q – это утверждения, при этом P является предусловием, а Q – постусловием [Meyer2005].

ПРИМЕЧАНИЕ
Приведенная выше формула корректности определяет полную корректность (total correctness), которая гарантирует завершаемость операции A. Помимо этого существует понятие частичной корректности (partial correctness), которое гарантирует выполнение постусловия Q только при условии завершения выполнения операции A.

Рассмотрим следующую триаду Хоара:

{x = 5} x = x ^ 2 {x > 0}

Эта триада корректна, т.к. если перед выполнением операции x^2, предусловие выполняется и значение x равно 5, то после выполнения этой операции, постусловие (x больше нуля) будет гарантировано выполняться (при условии корректной реализации целочисленной арифметики). Из этого примера видно, что приведенное постусловие не является самым сильным. В приведенном примере самым сильным постусловием при заданном предусловии является {x = 25}, а самым слабым предусловием при заданном постусловии является {x > 0}. Из выполняемой формулы корректности всегда можно породить новые выполняемые формулы, путем ослабления постусловия или усиления предусловия.

Понятие “сильнее” и “слабее” пришли из логики. Говорят, что условие P1 сильнее, чем P2, а P2 слабее, чем P1, если выполнение условия P1 влечет за собой выполнение условия P2, но они не эквивалентны. (Например, условие x > 5 (P1), сильнее условия x > 0 (P2), поскольку при выполнении условия P1 выполняется и условие P2 (ведь, если x больше 5, то, естественно, что x больше 0), при этом эти условия не эквивалентны). Из этого следует, что условие True является слабейшим (поскольку при выполнении любого условия, выполняется условие True), а False – сильнейшим (поскольку по своему определению, любое условие, не равное False когда либо выполняется) (рисунок 2).

Figure2

Рисунок 2 – Сильные и слабые условия (P1 сильнее P2)

ПРИМЕЧАНИЕ
Введение таких понятий, как сильные и слабые условия необходимы для рассмотрения других тем, в частности, вопросов наследования.

суббота, 10 апреля 2010 г.

Замыкания в языке программирования C#

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

вторник, 6 апреля 2010 г.

Новости Цитатника

Я опять решил выделить время и выложить наиболее интересные цитаты, опубликованные за последнее время в Цитатнике.

Стив Макконнелл. Совершенный код

Как сказал Дэвид Грайс, подход к программированию не должен определяться используемыми инструментами. В связи с этим он проводит различие между программированием на языке (programming in language) и программирование с использованием языка (programming into language). Разработчики, программирующие "на" языке, ограничивают свое мышление конструкциями, непосредственно поддерживаемым языком. Если предоставляемые языком средства примитивны, мысли программистов будут столь же примитивными.
Разработчики, программирующие "с использованием" языка, сначала решают, какие мысли они хотят выразить, после чего определяют, как выразить их при помощи конкретного языка.
Глава 4.3 Волны развития технологий

Цитаты: Часть 1

Дж. Ханк Рейнвотера “Как пасти котов. Наставление для программистов, руководящих другими программистами”

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

Чем лучше вы знаете людей, которыми вам предстоит руководить, тем выше шансы на успех.
Глава 1. Как привыкнуть к роли руководителя

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

Цитаты: Часть 1

Джоэл Спольски. "Джоэл о программировании"
Продвижение хороших кодеров выдвижением их на другие должности, где требуется писать на человеческом языке, а не на С++, служит классической иллюстрацией принципа Питера: люди продвигаются по службе, пока не достигнут своего уровня некомпетентности.
Глава 7. Как принимать на работу менеджера программы?

Идея рекламы состоит в том, чтобы врать и не быть пойманным.
Глава 37. Второе письмо о стратегии: что сначала - курица или яйцо.

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

Цитаты: Часть 2, Часть 3, Секреты айсберга, Справочник бойца по проведению собеседования

Скотт Мейерс. Эффективное использование С++

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

Правило 29. Стремитесь, чтобы программа была безопасна относительно исключений

Цитаты

Гради Буч. Объектно-ориентированный анализ и проектирование

Абстракция и икапсуляция дополняют друг друга: абстрагирование направлено на наблюдаемое поведение объекта, а инкапсуляция занимается внутренним устройством.
Глава 2.1 Инкапсуляция

Разумная инкапсуляция локализует те особенности проекта, которые могут подвергнуться изменениям.
Глава 2.1 Инкапсуляция

Сокрытие информации - понятие относительное: то, что спрятано на одном уровне абстракции, обнаруживается на другом уровне.
Глава 2.1 Инкапсуляция

Деление программы на модули бессистемным образом иногда гораздо хуже, чем отсутствие модульности вообще.
Глава 2.1 Модульность

Цитаты: Часть 3. Объектная модель. Основные определения, Часть 4

Эдвард Йордон. Путь камикадзе

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

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

Для проведения переговоров нелишними будут такие вопросы, как «обанкротится ли организация, если система будет готова не к 1-му сентября, а к 5-му?» или «все хотят, чтобы работа была сделана хорошо, быстро и дешево. Все знают, что реально можно выполнить только два требования из трех. Какие именно два для вас важнее?»
Глава 3.2 Допустимые компромиссы

Цитаты: Часть 1, Часть 2

Алан Шаллоуей и Джеймс Р. Тротт. Шаблоны проектирования

Шаблоны позволяют нам видеть лес за деревьями, поскольку помогают поднять уровень мышления.
Глава 5. Зачем нужно изучать шаблоны проектирования

Наличие возможности реализовать что-либо вовсе не означает, что это обязательно должно быть выполнено.
Глава 13. Принцип проектирования от контекста

Цитаты: Часть 3, Несколько слов о работе с заказчиком

суббота, 3 апреля 2010 г.

[Book ANN] The Design of Design by Frederick P. Brooks

Brooks Совсем недавно вышла новая книга Фредерика Брукса, автора знаменитого "Мифического человеко-месяца" - "The Design of Design – essays from a computer scientist".

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

"За последние шесть десятков лет я участвовал в проектировании систем в пяти различных областях: аппаратной части компьютеров, программного обеспечения, домов, книг и организаций. В каждой из них у меня была роль главного проектировщика или соавтора системы. Процесс проектирования меня интересует очень давно; тема моей диссертации 1956 года "Аналитическое проектирование систем автоматической обработки данных" ("The analytic design of automatic data processing systems"). Возможно сейчас пришло время более зрелых размышлений".

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

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

Краткое содержание книги

Section I: Models of Design
Section II: Collaboration and Telecollaboration
Section III: Design Perspectives
Section IV: A Computer Scientist’s Dream System for Designing Houses
Section V: Great Designers
Section VI: Trips through Design Spaces Case Studies

Дополнительные ресурсы об этой книге:

1. Fred Brooks, "Is There a Design of Design?" NSF Science of Design Workshop, November 2003 (3 pp., pdf)

2. Summary of Brooks' talk on "Collaboration and Telecollaboration in Design"

3. Fred Brooks, "The Design of Design", video of talk at CMU in 2002, which is an updated version of his Turing Award lecture (wmv) (с исходной ссылкой какие-то проблемы, поэтому я нашел вроде бы тоже самое видео на youtube).

3.  Книга входит в список This Week's Developer Reading List от Dr.Dobb's от 25 марта 2010

4. Обзор книги от Michael Keeling

5. Обзор книги от Hector Correa (описывает подробное содержимое первых трех разделов и кратко касается трех последних)

четверг, 25 марта 2010 г.

О переводе блога Эрика Липперта

Думаю, многие профессиональные .net разработчики знают Эрика Липперта (Eric Lippert), как ведущего разработчика компилятора C# и как одного из самых известных блоггеров по этой тематике.

В своем блоге, который называется “Fabulous Adventures In Coding” Эрик публикует довольно много интересных постов, прежде всего о языке программирования C#, о его новых возможностях, о подводных камнях языка, описывает темные места и т.п., ну и много чего интересного по смежным (и не очень) темам.

Помимо блога на английском языке существует его “младший брат”, вариант блога на русском языке – “Невероятные приключения в коде”. В последние несколько месяцев на русском варианте блога было некоторое затишье и я решил помочь Антону Злыгостеву (a.k.a. Sinclair) в этом деле.

Итак, на сегодняшний день, уже выложены переводы четырех новых сообщений. Это “Простые имена не так уж просты. Часть 2.”, “Трое судей”, “О вреде замыканий на переменных цикла” и “Замыкания на переменных цикла. Часть 2”, помимо этого уже готов перевод еще четырех сообщений (они будут публиковаться по одному-два в день), ну а над остальными я интенсивно работаю:)

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