Лучшая практика для образцового дизайна в Ruby on Rails

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

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

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

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

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

8
задан James A. Rosen 24 September 2008 в 19:11
поделиться

7 ответов

Я покрываю это в одном из моих крупных приложений, просто удостоверившись, что таблицы/модели концептуально сгруппированы по имени (с почти 1:1 образцовые таблицей отношения). Пример:

events
event_types
event_groups
event_attendees
etc...

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

8
ответ дан 5 December 2019 в 05:09
поделиться

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

10
ответ дан 5 December 2019 в 05:09
поделиться

Необходимо определенно использовать одну модель на таблицу для использования в своих интересах всего волшебства ActiveRecord.

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

Например, Вы могли иметь:

app/models/admin/user.rb
app/models/admin/group.rb

для моделей Admin:: Пользователь и Администратор:: Группа, и

app/models/publishing/article.rb
app/models/publishing/comment.rb

для публикации:: статья и публикация:: комментарий

И т.д...

6
ответ дан 5 December 2019 в 05:09
поделиться

Прежде, чем перейти в создании 70 моделей, рассмотрите этот вопрос помочь Вам решить:

Каждую из Ваших таблиц считали бы "объектом", например, "автомобильная" таблица или некоторые таблицы содержит только информацию отношений, все столбцы внешнего ключа, например?

В направляющих только "объектные" таблицы становятся моделями! (За некоторым исключением для определенных типов ассоциаций), Таким образом, вероятно, что, если у Вас есть только 5 групп функциональности, у Вас не могло бы быть 70 моделей. Кроме того, если группы функциональности, которую Вы упомянули, весьма отличаются, они могут даже подойти лучше всего в своем собственном приложении.

4
ответ дан 5 December 2019 в 05:09
поделиться

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

В классе на версию таблицы table version Вы не можете легко вытянуть общую функциональность в базовый класс. Вместо этого вытяните его в модуль. Иерархия как следующее могла бы оказаться полезной:

app/models/admin/base.rb - module Admin::Base, included by all other Admin::xxx
app/models/admin/user.rb - class Admin::User, includes Admin::Base
app/models/admin/group.rb - class Admin::Group, includes Admin::Base
1
ответ дан 5 December 2019 в 05:09
поделиться

Не зная больше деталей о природе этих семидесяти таблиц и их концептуальных отношений не действительно возможно дать хороший ответ. Эти таблицы прежней версии или Вы, разработали это с нуля?

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

Лично, я приложил бы много сил для не того, чтобы работать с семьюдесятью таблицами просто, потому что это - очень большая работа - семьдесят Моделей и Контроллеры и их 4 + представления, помощники, разметки, и тестирует не говоря уже о проблеме загрузки в память хранения дизайна в ind. Если, конечно, я не становился заплаченным по часам и достаточно хорошо компенсировать повторение.

4
ответ дан 5 December 2019 в 05:09
поделиться

Это уже упоминается, трудно дать достойный совет, не зная Вашу схему базы данных и т.д., однако, я склонился бы к созданию 70 + модели, (один для каждой из Ваших таблиц.)

Вы можете сходить с рук отказ от некоторой модели, но для стоимости (negliable), у Вас могут также быть они там.

Вы не должны создавать контроллер + представления для каждой модели (как отвечено srboisvert). Вам только нужен контроллер для каждого ресурса (который я ожидал бы быть много меньше чем 70 - вероятно, только 10 или приблизительно 15 оценок по Вашему описанию).

1
ответ дан 5 December 2019 в 05:09
поделиться
Другие вопросы по тегам:

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