Что такое & ldquo; Выполнить вокруг & rdquo; идиома?

Все более популярная библиотека D3 обрабатывает странности добавления / управления svg очень хорошо. Вы можете захотеть использовать его в отличие от jQuery hacks, упомянутых здесь.

HTML


Javascript

var circle = d3.select("svg").append("circle")
    .attr("r", "10")
    .attr("style", "fill:white;stroke:black;stroke-width:5");

146
задан Roman C 20 March 2016 в 08:42
поделиться

7 ответов

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

public interface InputStreamAction
{
    void useStream(InputStream stream) throws IOException;
}

// Somewhere else    

public void executeWithFile(String filename, InputStreamAction action)
    throws IOException
{
    InputStream stream = new FileInputStream(filename);
    try {
        action.useStream(stream);
    } finally {
        stream.close();
    }
}

// Calling it
executeWithFile("filename.txt", new InputStreamAction()
{
    public void useStream(InputStream stream) throws IOException
    {
        // Code to use the stream goes here
    }
});

// Calling it with Java 8 Lambda Expression:
executeWithFile("filename.txt", s -> System.out.println(s.read()));

// Or with Java 8 Method reference:
executeWithFile("filename.txt", ClassName::methodName);

код вызова не должен волноваться об открываться/очищать стороне - это будет заботиться о executeWithFile.

Это было откровенно болезненно в Java, потому что закрытия были так многословны, начиная с Java, как который могут быть реализованы 8 лямбда-выражений на многих других языках (например, лямбда-выражения C# или Groovy), и этот особый случай обрабатывается начиная с Java 7 с try-with-resources и AutoClosable потоки.

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

140
ответ дан Jon Skeet 20 March 2016 в 08:42
поделиться

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

Java не является языком, я принял бы решение выполнить в этом. Это более стильно для передачи закрытия (или лямбда-выражение) как аргумент. Хотя объекты возможно эквивалентны закрытиям .

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

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

7
ответ дан Bill Karwin 20 March 2016 в 08:42
поделиться

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

//... chunk of init/preparation code ...
task A
//... chunk of cleanup/finishing code ...

//... chunk of identical init/preparation code ...
task B
//... chunk of identical cleanup/finishing code ...

//... chunk of identical init/preparation code ...
task C
//... chunk of identical cleanup/finishing code ...

//... and so on.

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

//pseudo-code:
class DoTask()
{
    do(task T)
    {
        // .. chunk of prep code
        // execute task T
        // .. chunk of cleanup code
    }
};

DoTask.do(task A)
DoTask.do(task B)
DoTask.do(task C)

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

Смотрят на это сообщение для примера C#, и эта статья для примера C++.

44
ответ дан e.James 20 March 2016 в 08:42
поделиться

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

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

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

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

3
ответ дан Brian 20 March 2016 в 08:42
поделиться

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

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

идея с выполняется - вокруг, то, что лучше, если можно факторизовать шаблонный код. Это сохраняет Вас некоторый ввод, но причина более глубока. Это - принцип don't-repeat-yourself (DRY) здесь - Вы изолируете код к одному местоположению поэтому, если существует ошибка, или необходимо изменить его, или Вы просто хотите понять его, это - все в одном месте.

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

можно быть знакомы с некоторыми общими падежами в Java. Каждый - фильтры сервлета. Другой - AOP вокруг совета. Одна треть является различными xxxTemplate классами в Spring. В каждом случае у Вас есть некоторый интерфейсный объект, в который Ваш "интересный" код (говорят запрос JDBC, и обработка набора результатов) введен. Интерфейсный объект делает "перед" частью, вызывает интересный код и затем делает "после" части.

7
ответ дан Willie Wheeler 20 March 2016 в 08:42
поделиться

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

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

А позже:

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

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

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

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

7
ответ дан 23 November 2019 в 22:37
поделиться

Если вы хотите отличные идиомы, вот они:

//-- the target class
class Resource { 
    def open () { // sensitive operation }
    def close () { // sensitive operation }
    //-- target method
    def doWork() { println "working";} }

//-- the execute around code
def static use (closure) {
    def res = new Resource();
    try { 
        res.open();
        closure(res)
    } finally {
        res.close();
    }
}

//-- using the code
Resource.use { res -> res.doWork(); }
0
ответ дан 23 November 2019 в 22:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: