Почему "эксплицитность" считается хорошей вещью?

Я часто слышу, как люди хвалят языки, фреймворки,конструкции и т. д. за "откровенность". Я пытаюсь понять эту логику. Цель языка, рамок и т. д. это скрыть сложность. Если это заставляет вас явно указывать все виды деталей, то это не скрывает большой сложности, а только перемещает ее. Что такого замечательного в explicitness и как вы делаете язык / фреймворк / API "явным", все еще заставляя его служить своей цели скрывать сложность?

13 ответов


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

Hack C++ в течение десяти или двух лет, и вы поймете, что я имею в виду.


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

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

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

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

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


Я считаю, что explicit относится к знанию точно, что он делает, когда вы его используете. Это отличается от того, чтобы точно знать, как это делается, что является сложной частью.


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


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


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

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


быть явным и неявным-это все о том, что вы скрываете и что вы показываете.

В идеале вы выставляете концепции, которые либо заботят пользователя, либо должны заботиться (хотят они этого или нет).

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

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

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

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

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


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

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

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

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

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


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

например, C++ имеет const ключевое слово для переменных, значения которых не должны изменяться. Если программа пытается изменить эти переменные, компилятор может заявить, что код, вероятно, ошибочен.


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

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

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

double i = 5.0;

если вместо этого вы были объявить его как

var i = 5;

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


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

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

например, они не очень явные:

while (condition);

int MyFunction()

bool isActive;         // In C# we know this is initialised to 0 (false)

a = b??c;

double a = 5;

double angle = 1.57;

а это:

while (condition)
    /* this loop does nothing but wait */ ;

private int MyFunction()

int isActive = false;  // Now you know I really meant this to default to false

if (b != null) a = b; else a = c;

double a = 5.0;

double angleDegrees = 1.57;

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


в некоторых случаях противоположностью является "магия" - как в "тогда происходит чудо".

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


цель фреймворков, перемещающих вещи, - удалить дублирование в коде и облегчить редактирование фрагментов, не нарушая всего этого. Когда у вас есть только один способ сделать что - то, например, сказать SUM(x, y); Мы точно знаем, что это собирается делать, когда нужно переписать, и если вы должны, вы можете, но маловероятно. Противоположностью этому являются языки программирования, такие как .NET, которые предоставляют очень сложные функции, которые вам часто придется переписывать, если вы это делаете что угодно, только не очевидный простой пример.