Выявление удаленного интерфейса или модели объекта

StackOverflow https://stackoverflow.com/questions/37041

  •  09-06-2019
  •  | 
  •  

Вопрос

u003Cp>У меня есть вопрос о лучшем способе разоблачения асинхронного удаленного интерфейса.u003C/p>u003Cp> Условия следующие:u003C/p>u003Cul>u003Cli> Протокол асинхронноu003C/li>u003Cli> Третья сторона может изменить данные в любое времяu003C/li>u003Cli> Командование обратно-обратной поездки может быть значительнымu003C/li>u003Cli> Модель должна быть хорошо подходит для взаимодействия с пользовательским интерфейсомu003C/li>u003Cli> Протокол поддерживает запросы по сравнению с определенными объектами, как и модельu003C/li>u003C/ul>u003Cp> В качестве средства улучшения моих навыков в этой области (и увеличить свою Java в целом), я начал u003Ca href="http://Telharmonium.devjavu.com/" rel="nofollow noreferrer">проектu003C/a> по созданию фронтального конца на основе Eclipse для u003Ca href="http://xmms2.xmms.se" rel="nofollow noreferrer">XMMS2u003C/a> (описано ниже).u003C/p>u003Cp> Итак, вопрос в том; Как я должен разоблачить удаленный интерфейс как аккуратную модель данных (в данном случае управление отслеживанием и обработку событий)?u003C/p>u003Cp> Я приветствую что-нибудь, от общих дискуссий до разжигания имен и конкретных примеров и патчей :)u003C/p>u003Chr>u003Cp> Моя основная цель здесь - узнать об этом классе проблем в целом. Если мой проект может получить от этого, хорошо, но я представляю его строго, что есть что -то, чтобы начать обсуждение.u003C/p>u003Cp> Я внедрил абстракцию протокола, которую я называю u003Ca href="http://telharmonium.devjavu.com/browser/trunk/xmms2-client" rel="nofollow noreferrer">«клиентом»u003C/a> (по устаревшим причинам), которая позволяет мне получить доступ к большинству экспонированных функций, используя методы вызовов, с которыми я доволен, даже если это далеко не идеально.u003C/p>u003Cp> Особенности, предоставляемые Daemon XMMS2,-это такие вещи, как поиск треков, получение метадат и манипуляция, изменение состояния воспроизведения, загрузочные плейлисты и т. Д., И так далее.u003C/p>u003Cp> Я нахожусь в середине обновления до последнего стабильного выпуска XMMS2, и я подумал, что могу также исправить некоторые яркие недостатки моей текущей реализации.u003C/p>u003Cp> Мой план состоит в том, чтобы построить лучшую абстракцию поверх интерфейса протокола, который позволяет более естественно взаимодействовать с демона. Текущая реализация u003Ca href="http://telharmonium.devjavu.com/browser/trunk/xmms2-model" rel="nofollow noreferrer">«модели»u003C/a> трудно использовать и, откровенно говоря, довольно уродливая (не говоря уже о том, что пользовательский код, который является действительно ужасным банкоматом).u003C/p>u003Cp> Сегодня у меня есть интерфейс u003Ca href="http://telharmonium.devjavu.com/browser/trunk/xmms2-model/src/se/fnord/xmms2/model/Tracks.java" rel="nofollow noreferrer">трековu003C/a> , который я могу использовать, чтобы получить экземпляры классов u003Ca href="http://telharmonium.devjavu.com/browser/trunk/xmms2-model/src/se/fnord/xmms2/model/Track.java" rel="nofollow noreferrer">трековu003C/a> на основе их идентификатора. Поиск выполняется через интерфейс u003Ca href="http://telharmonium.devjavu.com/browser/trunk/xmms2-model/src/se/fnord/xmms2/model/Collections.java" rel="nofollow noreferrer">коллекцийu003C/a> (несчастное столкновение пространства имен), который я бы предпочел перенести на треки, я думаю.u003C/p>u003Cp> Любые данные могут быть изменены третьей стороной в любое время, и это должно быть должным образом отражено в модели и распределенных распределениях измененийu003C/p>u003Cp> Эти интерфейсы обнажаются при подключении, возвращая иерархию объекта, которая выглядит так:u003C/p>u003Cul>u003Cli> Связьu003Cul>u003Cli> Воспроизведение GetPlayback ()u003Cul>u003Cli> Играть, сделать паузу, прыгать, текущий трек и т. Д.u003C/li>u003Cli> Разоблачить изменения состояния воспроизведенияu003C/li>u003C/ul>u003C/li>u003Cli> Треки getTracks ()u003Cul>u003Cli> Трек getTrack (id) и т. Д.u003C/li>u003Cli> Разоблачить обновления трековu003C/li>u003C/ul>u003C/li>u003Cli> Коллекции getCollection ()u003Cul>u003Cli> Загружать и манипулировать плейлистами или названные коллекцииu003C/li>u003Cli> Query Media Libraryu003C/li>u003Cli> Разоблачить обновления коллекцииu003C/li>u003C/ul>u003C/li>u003C/ul>u003C/li>u003C/ul>
Это было полезно?

Решение

u003Cp>Для асинхронного бита я бы предложил зарегистрироваться в u003Ccode>java.util.concurrentu003C/code> , и особенно u003Ccode>Futureu003C/code> . Будущий интерфейс используется для представления объектов, которые еще не готовы, но создаются в отдельном потоке. Вы говорите, что объекты могут быть изменены в любое время третьей стороной, но я все равно предлагаю вам использовать здесь неизменные объекты возврата, а вместо этого есть отдельный журнал потока/события, на который вы можете подписаться, чтобы их заметить, когда истекают объекты. У меня мало программирования с пользовательскими интерфейсами, но я считаю, что использование будущих для асинхронных вызовов позволит вам получить отзывчивый графический интерфейс, а не тот, который ждал ответа на сервер.u003C/p>u003Cp> Для запросов я бы предложил использовать цепочку метода для создания объекта запроса, и каждый объект, возвращаемый методом цепочкой, должен быть u003Ccode>Iterableu003C/code> . Подобно тому, как модель Джангоса. Скажите, что у вас есть u003Ccode>QuerySetu003C/code> , который реализует u003Ccode>Iterableu003C/code> . Затем вы можете позвонить u003Ccode>allSongs()u003C/code> , который вернет результат, итерацию по всем песням. Или u003Ccode>allSongs().artist("Beatles")u003C/code> , и у вас будет итерация над всеми песнями Betles. Или даже u003Ccode>allSongs().artist("Beatles").years(1965,1967)u003C/code> и так далее.u003C/p>u003Cp> Надеюсь, это поможет как отправная точка.u003C/p>

Другие советы

u003Cp>Итерапильно имеет только метод итератор get () или что -то. Так что не нужно строить какой -либо запрос или выполнять какой -либо код, пока вы не начнете итерацию. Это делает выполнение в вашем примере избыточным. Тем не менее, поток будет заблокирован до тех пор, пока не будет доступен первый результат, поэтому вы можете рассмотреть возможность использования исполнителя для запуска кода для запроса в отдельном потоке.u003C/p>
u003Cp>@ u003Ca href="https://stackoverflow.com/questions/37041/exposing-a-remote-interface-or-object-model#37175">Staaleu003C/a>u003C/p>u003Cp> Это, безусловно, возможно, но, как вы отмечаете, это сделало бы его блокировку (дома для чего -то вроде 10 секунд из -за спящих дисков), что означает, что я не могу использовать его, чтобы напрямую обновить пользовательский интерфейс.u003C/p>u003Cp> Я мог бы использовать итератор для создания копии результата в отдельном потоке, а затем отправить его в пользовательский интерфейс, но хотя решение итератора само по себе довольно элегантно, оно не очень хорошо подходит. В конце концов, что -то реализующее u003Ca href="http://help.eclipse.org/stable/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredContentProvider.html" rel="nofollow noreferrer">IstructuredContentProvideru003C/a> необходимо вернуть массив всех объектов, чтобы отобразить его в u003Ca href="http://help.eclipse.org/stable/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/TableViewer.html" rel="nofollow noreferrer">TableVieweru003C/a> , поэтому, если я смогу уйти с получением чего -то подобного от обратного вызова ... :)u003C/p>u003Cp> Я подумаю еще. Я мог бы просто что -то выработать. Это придает коду красиво.u003C/p>
u003Cp>@ u003Ca href="https://stackoverflow.com/questions/37041/exposing-a-remote-interface-or-object-model#37093">Staaleu003C/a> : Спасибо!u003C/p>u003Cp> Использование будущего для асинхронных операций интересно. Единственным недостатком является то, что он не предоставляет обратные вызовы. Но опять же, я попробовал этот подход и посмотрю, куда меня это принесло :)u003C/p>u003Cp> В настоящее время я решаю аналогичную проблему с помощью рабочей потока и блокирующей очередь для отправки ответов входящих команд, но этот подход не очень хорошо переводится.u003C/p>u003Cp> Удаленные объекты могут быть изменены, но, поскольку я использую потоки, я стараюсь держать объекты неизменными. Моя нынешняя гипотеза заключается в том, что я отправлю события уведомлений на обновлениях по пути в формеu003C/p>u003Cpre> u003Ccode>somehandlername(int changes, Track old_track, Track new_track)u003C/code>u003C/pre>u003Cp> Или аналогично, но тогда я мог бы получить несколько версий того же трека.u003C/p>u003Cp> Я обязательно посмотрю на цепочку метода Джангоса. Я смотрел на некоторые подобные конструкции, но не смог придумать хороший вариант. Возвращение чего -то итерационного интересно, но запрос может занять некоторое время, и я бы не хотел на самом деле выполнять запрос, прежде чем он полностью построен.u003C/p>u003Cp> Возможно, что -то вродеu003C/p>u003Cpre> u003Ccode>Tracks.allSongs().artist("Beatles").years(1965,1967).execute()u003C/code>u003C/pre>u003Cp> Возвращение будущего может работать ...u003C/p>
u003Cp>Мои выводы до сих пор;u003C/p>u003Cp> Я разорван тем, использовать ли Getters для объектов трека или просто разоблачить участники, поскольку объект неизменен.u003C/p>u003Cpre> u003Ccode>class Track { public final String album; public final String artist; public final String title; public final String genre; public final String comment; public final String cover_id; public final long duration; public final long bitrate; public final long samplerate; public final long id; public final Date date; /* Some more stuff here */ }u003C/code>u003C/pre>u003Cp> Любой, кто хочет знать, когда что -то случилось с треком в библиотеке, будет реализовать это ...u003C/p>u003Cpre> u003Ccode>interface TrackUpdateListener { void trackUpdate(Track oldTrack, Track newTrack); }u003C/code>u003C/pre>u003Cp> Вот как строятся запросы. Цепные призывы к вашему сердцу содержание. Жюри все еще не входы (), хотя. Отсутствуют некоторые детали, например, как я должен справиться с подстановочными знаками и более продвинутыми запросами с дизъюнкциями. Мне может понадобиться некоторая функциональность обратного u003Ca href="http://www.cse.wustl.edu/~schmidt/PDF/ACT.pdf" rel="nofollow noreferrer">вызоваu003C/a> Возможно, это произойдет в дополнительном слое.u003C/p>u003Cpre> u003Ccode>interface TrackQuery extends Iterable { TrackQuery years(int from, int to); TrackQuery artist(String name); TrackQuery album(String name); TrackQuery id(long id); TrackQuery ids(long id[]); Future get(); }u003C/code>u003C/pre>u003Cp> Некоторые примеры:u003C/p>u003Cpre> u003Ccode>tracks.allTracks(); tracks.allTracks().artist("Front 242").album("Tyranny (For You)");u003C/code>u003C/pre>u003Cp> Интерфейс треков - это в основном только клей между соединением и отдельными треками. Это будет тот, который внедряет или управляет кэшированием метадат, если таковые имеются (как и сегодня, но я думаю, что я просто удалю его во время рефакторинга и посмотрю, действительно ли он мне нужно). Кроме того, это обеспечивает обновления треков Medialib, так как это было бы слишком много работы, чтобы реализовать их на треке.u003C/p>u003Cpre> u003Ccode>interface Tracks { TrackQuery allTracks(); void addUpdateListener(TrackUpdateListener listener); void removeUpdateListener(TrackUpdateListener listener); }u003C/code>u003C/pre>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top