Дизайн API для матричной библиотеки?

Я довольно давно занимаюсь разработкой небольшой Java библиотеки для работы над задачами линейной алгебры и мне приходилось часто принимать решения по поводу дизайна публичного API. До этого момента все шло отлично. Но недавно появился один момент который не дает мне покоя. Хотелось бы узнать мнение сообщества о том как поступить в такой ситуации.


В чем суть. Есть разреженные матрицы, которые в основном хранят нули и лишь несколько значимых элементов. Сейчас я на пороге выбора добавлять ли в публичный API для разреженных матриц метод toArray(). С одной стороны у пользователя должна быть такая возможность (конвертировать матрицу в двумерный массив). С другой — эта операция прямо противоречит всей идеологии разреженных матриц — уменьшение используемой памяти.


Еще одна сторона медали — я решил разделить семейство плотных и разреженных матриц на уровне интерфейса. И сейчас я не могу придумать ни одного метода, который был бы характерен для плотных но не применим к разреженным. Метод toArray() очень подходит на эту роль, в то время как метод cardinality() — количество не нулевых элементов — явный претендент для API разреженных.


Резюмируя. Есть потребность придумать характерный метод для плотной матрицы. Есть кандидат — самый низко висящий фрукт — toArray(). Префекционист во мне говорит что toArray() должен быть у всех. Лентяй и костыльный программист — только у плотных.


Очень прошу совета у сообщества что делать со злополучным методом.
  • Вопрос задан
  • 3576 просмотров
Решения вопроса 1
Colwin
@Colwin
Ведущий Java-разработчик
Сразу: код не смотрел.

Однако по концепции я бы лично не стал выносить toArray() в общий интерфейс, т.к. слабо могу себе представить, где было бы необходимо преобразовывать разряженную матрицу в обычную. Лучше посмотреть сценарии, когда такое преобразование кажется логичным, и вынести в интерфейс операции, которые вынуждают Вас выносить toArray() в общий интерфейс. Для разряженных операций эта операция по определению дорогая, и, IMHO, в реальных задачах от этого не много смысла.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@Artyushov
Мне кажется, что метод toArray() должен быть реализован в обоих типах матриц. Если есть интерфейс Matrix, то в нём должен быть метод toArray(). Уже в конкретной реализации разреженной матрицы можно добавить метод, предствляющий матрицу в более компактном виде.

Специфичность разреженной матрицы должна быть на уровне реализации, например использование более оптимальных алгоритмов при перемножении и т.п. Это как LinkedList и ArrayList. Методы-то в них одинаковые, пользователь сам решает для чего он будет использовать список и выбирает реализацию. Кажется, что в вашем случае должно быть так же.
Ответ написан
Что-то не увидел в API la4j таких очевидных, на мой взгляд, вещей, как итераторы (или функторы). Чтобы обрабатывать элементы матрицы построчно или по столбцам, например. Если это вообще нужно, конечно.

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

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

Задача API не только в том, чтобы давать возможности, но и подталкивать к выбору правильных решений. А использование «плотного» итератора для разреженных матриц — неправильное решение, так что его можно было бы в интерфейс разреженных матриц не добавлять совсем.
Ответ написан
@1nd1go
Есть разреженные матрицы, которые в основном хранят нули и лишь несколько значимых элементов. <...> С другой — эта операция прямо противоречит всей идеологии разреженных матриц — уменьшение используемой памяти.

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

Разделять матрицы на уровне интерфейса если вы не можете придумать действительно значимые различия, может быть неправильным. Вспомните интерфейс List и имплментации LinkedList и ArrayList. Было бы странно их разделять на уровне интерфейса.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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