Представление узлов
Если мы хотим включить круглые скобки, нам нужно 5 видов узлов:
двоичные узлы: Добавить минус Mul Div
у них есть два потомка, левая и правая стороны
+
/ \
node node
узел для хранения значения: Val
нет дочерних узлов, только числовое значение
узел для отслеживания паренов: Paren
один дочерний узел для подвыражения
( )
|
node
Для Полиморфное решение, нам нужно иметь такие классовые отношения:
Существует виртуальная функция для всех узлов, называемая eval (). Если вы вызовете эту функцию, она вернет значение этого подвыражения.
Иногда, если вы не можете придумать хорошее имя функции, это признак того, что функция не имеет четкого и четкого фокуса и требует рефакторинга. Если это метод класса, возможно, класс тоже нуждается в рефакторинге.
Но стоит потрудиться над поиском наилучших возможных имен, так как это делает ваш код намного более понятным и удобным.
Обновление: Многие авторы программной инженерии говорили о важности именования. Пословицы о программировании (1975) Генри Ф. Ледгарда и Элементы стиля программирования (1978) Брайана Кернигана и П.Дж. Плэгера были ранними и все еще заслуживают внимания. Замечательный Code Complete Стива МакКоннелла (2-е издание, 2005 г.) является более свежим примером, в котором этой теме посвящена целая глава.
Элементы стиля программирования были частично заимствованы из статьи Странка и Уайта Элементы стиля , которая на самом деле имеет удивительную актуальность. Их упор на то, чтобы изложение было ясным и предельно кратким, применимо к нашему техническому письму и комментариям (и именам), но я всегда видел в этом аналогию того, что мы делаем при рефакторинге и улучшении нашего кода.
Покойный великий Фил Карлтон заметил известную шутку: «В информатике есть только две трудные проблемы - присвоение имен объектам и аннулирование кеш-памяти. Мой опыт подсказывает мне, что в этом много правды.
Правильное наименование вещей - это не только наука, но и искусство, и поэтому нет никаких жестких правил. Тем не менее, я иногда читаю правила Оттингера для именования переменных и классов , о которых следует помнить о некоторых хороших эвристиках. Одно из моих любимых - использовать словосочетания с существительными, такие как - person.getName () или bitTorrentClient.findPeersFromTracker (). В обоих случаях цель строки кода читается аналогично фразе на английском языке.
Я бы предпочел смехотворно длинные имена методов в контексте более крупного алгоритма, потому что это уменьшает необходимость смотреть на реализацию функции.
Имя вроде ReadPropertiesFromFileThenWriteToSession лучше, чем ReadProps .
Иногда можно уменьшить длину имени функции, просто перефразируя имя. Вместо:
void RetrievePropertiesFromRemoteStore()
Вы можете использовать:
void RetrieveRemoteProperties()
Вместо:
bool CheckToSeeIfUserIsAuthorized()
Используйте:
bool IsUserAuthorized()
Другой способ уменьшить это - переосмыслить, что делает функция. Вместо одной такой функции:
void GetUserProfileAndSetUpSession()
Вы могли бы иметь:
void GetUserProfile()
void SetupSession()
Каждый раз, когда я ударяюсь о кирпичную стену, пытаясь назвать функцию или процедуру, я возвращаюсь назад и очень много думаю о том, для чего, по моему мнению, она предназначена. Часто, если имя нелегко напрашивается само собой, это намек на то, что я не продумал, что на самом деле должна делать функция или процедура.
У вас есть процесс, который должен делать A, B, C , ..., X, Y и Z; вы не можете назвать процедуру doABCDEFGHIJKLMNOPQRSTUVWXYZ. Вы должны найти некоторую логическую группировку среднего уровня (возможно, несколько уровней группирования), которая разделяет процесс.
Иногда для поиска правильного имени требуется переместить код, чтобы он был разбит на несколько логических блоков.
Другая помощь заключается в том, чтобы инкапсулировать функции / процедуры (в зависимости от особенностей языка, на котором вы re using), чтобы имя могло быть короче (так как его имя можно интерпретировать в контексте его контейнера). Например, процедура «openFile» обычно должна просто открывать файл для чтения; но в контексте класса «UserPrefsFile» это могло бы иметь более конкретное значение.
Когда у вас заканчиваются разумные имена, просто используйте буквы алфавита. Когда они закончатся, выбирайте случайные слова из словаря. Таким образом, они никогда не смогут вас уволить, потому что вы единственный, кто понимает код.
Хех. Когда я прочитал заголовок вопроса, меня осенило, что процесс программирования можно описать как «проблему с поиском хороших имен для функций».
Ваши функции должны действительно указывать, что они делают! Но не слишком многословно. Это то, что вы со временем освоите, чтобы получить правильную функцию, потребуется немного практики.
Прочтите быстро this , чтобы увидеть кое-что, что я писал о подобных вещах некоторое время назад :) Убедитесь, что вы прочитали другую статью , которая вдохновила меня написать ее, и просмотрите комментарии.
Используя объектно-ориентированный подход помогает уменьшить эту проблему .. connectionsToAccessLines -> connexion.connect (System.getAccessLines ());
handleWallVisionSplit -> этот, я не совсем уверен, что он делает: D Но я бы сказал что-то вроде: wall.handleVision (Wall.split); или что-то в этом роде, я думаю, вы понимаете, что я имею в виду.
Кроме того, иногда, когда действительно трудно назвать слишком конкретную функцию, это может быть потому, что код недостаточно высокого уровня. Например: readSecondWordOfLine (a_line) -> line.split () [1].
Или sort (sortWithSecondWordOfLine ()) может стать, sort (line => split (line) [1]) .. Я знаю, что это не всегда возможно так чисто, как на всех языках, но вы меня понимаете. В C ++, например, вы можете использовать составные части bind и stl для построения одного выражения лайнера вместо создания нового метода.
Итак, я мог бы резюмировать это, сказав, что если у вас слишком технический метод - который обычно очень короткий, потому что в противном случае имя было бы легко найти, абстрагируя функциональные возможности, - хорошо создать новую функцию / класс, более обобщенный с абстрактным именем и используйте его непосредственно в первой функции.
Вы можете использовать нумерацию и постфиксы «_ *», чтобы избежать слишком большого количества имен в вашем коде:
void DoX()
void DoX_Decode1() <-- this name shows that this function is only used by DoX()
void DoX_Decode2()
void DoX_Decode3()
void DoX_Find1()
void DoX_Find2()
void DoX_Find3()
Вы также можете сгруппировать аналогичные функции с помощью префиксов:
void tcpip_ShowConnectDialog()
void tcpip_AcceptConnections()
void logging_WriteToFile()
void logging_UpdateLogWindow()
Таким образом вы получаете уникальные имена функций (помогает при поиске и поиске и замене) и при этом делаете их относительно короткими. Вы также избегаете хлопот с извлечением их в отдельный класс и отдельный файл кода. Просто используйте короткие префиксы, чтобы их можно было легко игнорировать и смотреть дальше.
Одно из предложений из книг по рефакторингу - посмотреть на длинный алгоритм и везде, где вы чувствуете, что есть блок в коде, который можно описать с помощью однострочного комментария, реорганизуйте этот блок в частный функция и используйте то, что находится в единственной строке, как имя функции. Это может быть очень долго, но если это поможет вам быстро прочитать алгоритм, это прекрасно. Полный код указывает хороший диапазон от 9 до 15 символов.
И не волнуйтесь, если это частная вспомогательная функция, рефакторинг имени позже не проблема