Статьи

Визуализация кода

При написании программного обеспечения мы работаем на двух уровнях:

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

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

Что значит  визуализировать  код? На самом простом уровне это понимание того, что делают отдельные заявления.

string a = "Hello"; 
string b = "world";
a = b;

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

while (stack.Count() > 1)
{
    var operation = stack.Pop() as IOperation;
    var result = operation.Execute(stack.Pop(), stack.Pop());
    stack.Push(result);
}

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

int Depth(ITreeNode node)
{
    if (node == null)
        return 0;
    return 1 + Math.Max(Depth(node.Left), Depth(node.Right));
}

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

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

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

public interface IAnimal
{
    void Accept(IAnimalVisitor visitor);
}
 
public class Dog : IAnimal { ... }
public class Cat : IAnimal { ... }
public class Fox : IAnimal { ... }
 
public interface IAnimalVisitor
{
    void VisitDog(Dog dog);
    void VisitCat(Cat cat);
    void VisitFox(Fox fox);
}

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

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

Например, в книжном интернет-магазине у меня могут быть такие понятия (классы), как книга, клиент, корзина покупок, почтовый адрес. Это все логические вещи реального мира с очевидными взаимодействиями. Если бы я вместо этого назвал их PurchaseasableItem, RegisteredUser, OrderItemList и DeliveryIndicationStringList, вы, вероятно, изо всех сил пытались бы понять, как одно связано с другим. Называть вещи сложно, но невероятно важно — плохое именование значительно усложнит разработку хорошей ментальной модели работы вашей системы.

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