Рубрики
Без рубрики

[PT-BR] Эвитандо “Избегает ссылок” com JPMS

Часто, когда мы разрабатываем наши программы, мы не замечаем возможных ошибок, которые… Помеченный java, jvm, pt br.

Часто, когда мы разрабатываем наши программы, мы не замечаем возможных ошибок , которые вставляются в код. Дело в том, что, в некоторых случаях, поведение, наше приложение может быть очень плотно. Идея этого поста, чтобы представить этих проблем, называется escaping references , и возможные решения.

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

  • 1 класс, называемый Книги , что это представление книги
package br.com.er.model;
public class Livro {

    public Livro(Long id, String nome, String autor, Double preco) {
        this.id = id;
        this.nome = nome;
        this.autor = autor;
        this.preco = preco;
    }

    private final Long id;
    private final String nome;
    private final String autor;
    private Double preco;

    public String getAutor() { return autor; }

    public void setPreco(Double preco) { this.preco = preco; }

    @Override
    public String toString() {
        return "Livro{" +
                + id +
                ", nome='" + nome + '\'' +
                ", autor='" + autor + '\'' +
                ", preco=" + preco +
                '}';
    }
}
  • 1 класс, называемый ColecaoDeLivros ответственность за оказание список книг, и некоторые модели поведения, чтобы обрабатывать ее.
package br.com.er.collection;
//imports omitidos
public class ColecaoDeLivros {

    public List livros;

    public ColecaoDeLivros() {
        livros = List.of(
                new Livro(1L, "Clean Code", "Uncle Bob", 119.99)
        );
    }

    public void mostrarLivros() {
        livros.forEach(System.out::println);
    }

    public Livro buscarPorAutor(String autor) {
        return livros.stream().
                filter(livro -> livro.getAutor().contains(autor))
                .findAny()
                .orElseThrow(RuntimeException::new);
    }
}
  • 1 класс Основной ответственность за выполнение кода.
package br.com.er;
import br.com.er.collection.ColecaoDeLivros;
public class Principal {

    public static void main(String... x) {

        ColecaoDeLivros cl = new ColecaoDeLivros();

        cl.mostrarLivros();
        System.out.println(cl.buscarPorAutor("Uncle Bob"));

    }
}

Приведенный выше код является 100% функциональным и мы можем гарантировать это, запустив свой класс Основное .

Intellij IDE, используемой для выполнения o код

/Library/Java/JavaVirtualMachines/jdk-11.0.9.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=50174:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/jv.martins/Documents/workspace/avoid-escaping-reference/out/production/avoid-escaping-reference br.com.er.Principal
Livro{id=1, nome='Clean Code', autor='Uncle Bob', preco=119.99}
Livro{id=1, nome='Clean Code', autor='Uncle Bob', preco=119.99}

Process finished with exit code 0

Мы будем делать незначительные изменения в классе Основное .

//resto do código omitido
public static void main(String... x) {

        ColecaoDeLivros cl = new ColecaoDeLivros();

        cl.mostrarLivros();
        cl.buscarPorAutor("Uncle Bob").setPreco(0.0);
        cl.mostrarLivros();
    }

Как мы можем наблюдать, метод setPreco класса Книги вызывается после метода buscarPorAutor класса ColecaoDeLivros . Это происходит потому, что возвращение buscarPorAutor Книги . За хорошие практики разработки, есть два варианта:

  1. Стать невозможно вызвать метод setPreco .

  2. Если удается вызвать метод setPreco , вызов не должен оказывать влияние, например, цен на книги, возвращается не должен быть изменен.

Снова запустить проект, результат будет:

/Library/Java/JavaVirtualMachines/jdk-11.0.9.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=50116:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/jv.martins/Documents/workspace/avoid-escaping-reference/out/production/avoid-escaping-reference br.com.er.Principal
Livro{id=1, nome='Clean Code', autor='Uncle Bob', preco=119.99}
Livro{id=1, nome='Clean Code', autor='Uncle Bob', preco=0.0}

Process finished with exit code 0

Как это не должно быть возможным, чтобы изменить цену возвращаемый объект, мы замечаем, что наше приложение не ведет себя как надо. Este é um exemplo de ускользающая ссылка . Мы меняем атрибут ” тип, через метод возвращает другой тип. В соответствии с правилами, будем модифицировать наш код, который не удается вызвать метод setPreco .

Первым вариантом, чтобы избежать проблемы уже отмечалось, является создание интерфейса Книги , который имеет только методы getter

package br.com.er.interfaces;

public interface ILivro {
    String getAutor();
} 

Теперь обменяем метод возвращения buscarPorAutor интерфейс создан.

//classe ColecaoDeLivros

public ILivro buscarPorAutor(String autor) {
        return livros.stream().
                filter(livro -> livro.getAutor().contains(autor))
                .findAny()
                .orElseThrow(RuntimeException::new);
    }

Это действие уже будет достаточно, чтобы код не компилируется.

Мы решаем ситуацию и теперь не удается вызвать метод setPreco . Утвердительный предыдущее было бы совершенно верно, если бы не способ, чтобы сделать литья ILivro для Книги .

public static void main(String... x) {

        ColecaoDeLivros cl = new ColecaoDeLivros();

        cl.mostrarLivros();
        ILivro livro = cl.buscarPorAutor("Uncle Bob");
        Livro livroConvertido = (Livro) livro;
        livroConvertido.setPreco(0.0);
        cl.mostrarLivros();
    }

Мы можем заметить, что путь для вызова метода setLivro стало труднее, но не невозможно. Приведенный выше код возвращает тот же результат, как прежде

/Library/Java/JavaVirtualMachines/jdk-11.0.9.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=49798:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/jv.martins/Documents/workspace/avoid-escaping-reference/out/production/avoid-escaping-reference br.com.er.Principal
Livro{id=1, nome='Clean Code', autor='Uncle Bob', preco=119.99}
Livro{id=1, nome='Clean Code', autor='Uncle Bob', preco=0.0}

Process finished with exit code 0

Масса энтао нао темос ума мадейра де эвитар дефинитиваменте эссес ускользающие ссылки ? Ответ вы увидите в следующем разделе

В JPMS является feature Java, которая направлена на модуляризации JDK. Из их ряд преимуществ, один из них обеспечивает лучшую инкапсуляцию наших компонентов. В этом разделе мы будем использовать эту feature чтобы избежать проблема com экранирование ссылок .

Первый шаг-это разделить приложение на модули и определить, какие классы будут в каждом модуле. Para o nosso exemplo, vamos de finir о примерах модуло ком как классика br.com.e r.коллекция. Колекао Де Ливрос , br.com.er.интерфейсы. Ливро e br.com.er.модель. Ливро . Именно структура модуля:

Вы, наверное, видели, что есть новый файл с именем module-info.java . Этот файл необходим для компиляции приложения, и в нем можно сделать несколько настроек. Мы можем определить, какие компоненты мы хотим, чтобы были выставлены вне модуля, укрепление туннеля и приложения мы можем определить, какие модули вы хотите использовать внутри модуля, в котором мы работаем. Чтобы лучше понять, давайте проверим содержимое файла.

module avoid.escaping.reference {

    exports br.com.er.collection;
    exports br.com.er.interfaces;
}

Зарезервированное слово module служит для определения модуля, который был назван Зарезервированное слово module служит для определения модуля, который был назван

Второй модуль будет иметь класс Основной и будет отвечать за реализацию проекта.

Модуль выполнения зависит от модуля avoid.escaping.reference и эта зависимость определяется в файле module-info|.

module avoid.escaping.reference.engine {

    requires avoid.escaping.reference;
}

Важно обратить внимание на один момент. Когда мы используем export , мы делаем экспорт пакетов (пакет в пакете), которые могут быть использованы за пределами модуля. Когда мы используем requires мы, требуя модуль, как все, и мы будем иметь доступ ко всем ресурсам которые были экспортированы из другого модуля.

Последнее замечание: для работы приложения, – добавить в путь сборки модуля avoid.escaping.reference.engine модуль избегать.экранирования.ссылки .

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

Код показывает ошибку компиляции, потому что не экспортируем класс Книги модуля avoid.escaping.reference , то для модуля выполнения ( avoid.escaping.reference.engine ) этот класс не существует. Используя этот подход, мы делаем невозможное вызов метода setPreco и достигли конечной цели.

Мы понимаем, что проблемы, упомянутые в посте, не всегда легко определить, и в этом ухудшается, потому что не каждое решение предотвращает на 100% проблему. Использование интерфейсов, в некоторых случаях отлично работает, потому что то, что мы сделали, чтобы заставить casting, не является реальностью для определенных проектов. Уже для других проектов, JPMS-это лучший вариант, потому что обеспечивает инкапсуляцию ресурсы, которые нельзя использовать за пределами модуля. Выбор будет зависеть от необходимости и конструкции. Любые вопросы, критику и предложения, я готов. До свидания!!

Ссылки на код

Оригинал: “https://dev.to/j_a_o_v_c_t_r/pt-br-evitando-escaping-references-45pb”