Является ли когда-либо плохой идеей сделать Java-объект доступным для общественности? - PullRequest
7 голосов
/ 17 февраля 2009

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

Я пытаюсь сэкономить каждую унцию мощности процессора и памяти, которую могу.

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

Пожалуйста, дайте мне знать, если это глупо.

Ответы [ 28 ]

2 голосов
/ 17 февраля 2009

Я почти уверен, что количество используемой памяти ничтожно мало. JVM может даже оптимизировать вызовы, чтобы сделать их встроенными в зависимости от реализации во время выполнения, если вы собираете для производства. Если вы разрабатываете это самостоятельно, это все равно может помочь, потому что, если у вас есть проблема с отслеживанием ошибок, вы можете установить точку останова в getter / setter и точно знать, когда вы меняете значения. Также не должно быть никакого кода для написания, потому что большинство современных IDE имеют функции для автоматического генерирования кода.

2 голосов
/ 17 февраля 2009

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

1 голос
/ 17 февраля 2009

ИМХО, для свойств, которые по своей природе просто предназначены для пассивного хранения данных и не могут сделать что-либо более сложное без полного изменения их значения с точки зрения пользователя API, геттеры и сеттеры являются просто ненужным образцом. Если свойство есть и по своей природе, очевидно, всегда будет, просто держатель данных, такой как класс, который используется аналогично структуре C, просто сделайте эту глупость общедоступной. Как более общее утверждение, лучшие практики могут легко стать пустой тратой времени или даже худшими, если применять их слишком усердно, не задумываясь о том, почему они являются лучшими. Черт, даже goto, возможно, время от времени оправданно.

1 голос
/ 17 февраля 2009

Это не глупо, но я думаю, что это тоже не очень хорошая идея.

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

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

1 голос
/ 18 февраля 2009

Если ваш приоритет - производительность, вы должны посмотреть на свой выбор виртуальной машины Java и то, как она выполняет программы. Настольная Java от Sun тратит МНОГО времени на профилирование и компиляцию Java-байтового кода в машинный код, что приводит к программам, которые могут работать очень быстро, но использовать много памяти.

Если вы обнаружите, что хотите использовать JVM на основе HotSpot, вам следует изучить все приемы, чтобы помочь ему. Методы получения и установки обычно являются встроенными (то есть заменяются непосредственно в машинном коде вместо вызова подпрограммы), а константы складываются. Операторы переключения для небольших диапазонов обычно преобразуются в таблицу переходов.

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

В мире Си человек вряд ли сможет перехитрить компилятор. В мире Java человек может помочь HotSpot, написав прямую Java.

1 голос
/ 17 февраля 2009

Я создал два маленьких класса и протестировал их.

  • Сначала я создал отдельный объект в качестве прототипа.

  • Затем я создал массив из 2 000 000, чтобы хранить их все.

  • Затем я запустил цикл, создал там новый экземпляр и взял значения из прототипа.

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

WithGS  Without
1.1323  1.1116

Diff  = 0.0207 secs.

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

Вот код:

PersonGetSet.java


public class PersonGetSet {
    private String name;
    private boolean deceased;

    public void setName( String name ) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    public void setDeceased( boolean deceased ) {
        this.deceased = deceased;
    }
    public boolean isDeceased() {
        return this.deceased;
    }

    public static void main( String [] args )  {
        PersonGetSet pb = new PersonGetSet();
        pb.setName( "name" );
        pb.setDeceased( true ) ;

        long start = System.currentTimeMillis();
        PersonGetSet [] array = new PersonGetSet[2000000];
        for( int i = 0 ; i < array.length; i++ ) {
            PersonGetSet personGs = new PersonGetSet();
            personGs.setName( pb.getName() );
            personGs.setDeceased( pb.isDeceased() );
            array[i] =  personGs;
        }
        System.out.println( "PersonGetSet took " + ( System.currentTimeMillis() - start ) + " ms. " );
    }
}


Person.java


public class Person {
    String name;
    boolean deceased;
    public static void main( String [] args )  {
        Person pb = new Person();
        pb.name=  "name" ;
        pb.deceased = true;

        long start = System.currentTimeMillis();
        Person [] array = new Person[2000000];
        for( int i = 0 ; i < array.length; i++ ) {
            Person simplePerson = new Person();
            simplePerson.name=  pb.name;
            simplePerson.deceased = pb.deceased;
            array[i] =  simplePerson;
        }
        System.out.println( "Person took " + ( System.currentTimeMillis() - start ) + " ms. " );
    }
}
1 голос
/ 17 февраля 2009

Потенциальные недостатки для использования

public final тип var ;

вместо

private final тип var ;

public тип get var () {return var ;}

(который я лично испытал) включают в себя:

  • Перспектива - как бы маловероятно сейчас это ни казалось - необходимость изменить представление в базовом классе или в каком-то будущем подклассе.

  • Потенциальная неловкость смешения открытых полей неизменяемого и изменяемого типа.

  • Затрудняюсь вспомнить, какие классы используют public final, а какие get var .

  • Надоело объяснять это несоответствие кому-то еще, кто может позже увидеть исходный код.

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

1 голос
/ 17 февраля 2009

Никогда не знаешь, всегда кодируй, как будто люди, которые читают твой код, знают, где ты живешь и являются серийными убийцами. Даже если вы разрабатываете код только для себя, попробуйте (imo) сделать это так, как если бы вы разрабатывали в команде. Таким образом, вы привыкните к созданию удобочитаемого кода. Что касается снижения производительности, может быть, лучше сделать это в C-образном формате, чем, если вам действительно действительно нужен каждый бит вашей памяти и каждый цикл вашего процессора.

0 голосов
/ 17 февраля 2009

Это всегда плохая идея, чтобы сделать нефинальные поля общедоступными.

Что если позже вы захотите добавить уведомление о событии?

Что если позже вы захотите создать подкласс и изменить поведение?

Что делать, если есть какие-то ограничения по полям, которые вы хотите применить?

TofuBeer показывает класс Point с окончательными полями - это нормально. Тем не менее, класс Point в AWT не использует финалы, и это вызвало у меня большое горе на ранних этапах Java.

Я писал некоторый трехмерный код и хотел создать подкласс Point, чтобы при каждом изменении x & y я мог автоматически настраивать z по мере необходимости. Поскольку поля Point были общедоступными, невозможно было узнать, когда x или y изменились!

0 голосов
/ 17 февраля 2009

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

Одним из ключевых аспектов ООП является указание объекту сделать что-то вместо того, чтобы вытаскивать кусочки и делать это самостоятельно. * например 1005 *

double ret = myObj.calculateReturn()

против

int v = myObj.getValue();
int ov = myObj.getOldValue();
double ret = (v-ov)/ov * 100; // do I work about dividing by zero etc.? 

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

...