Scala Установить реализацию для использования в бизнес-модели? - PullRequest
1 голос
/ 21 октября 2010

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

import scala.collection._

class Person (var name: String) {
    private val _friends = new mutable.HashSet[Person]

    def befriends     (p: Person) { _friends+=p }
    def fallsOutWith  (p: Person) { _friends-=p }
    def friends () = _friends toSet
    override def toString = name
}

Пока чтотак хорошо:

val brad     = new Person("Brad Pitt")
val angelina = new Person("Angelina Jolie")

brad befriends angelina
angelina befriends brad 

Хорошие вещи!Последний штрих, давайте посмотрим список всех друзей Брэда:

brad.friends.foreach(println)

Это работает, и мы собираемся покорить мир нашей замечательной социальной сетью, которая на 100% Scala!

Теперь перейдем к скучным техническим деталям.Нам нужно было бы сохранить данные, и db4o кажется хорошим выбором, немного кода:

 db store brad // job done!

А затем восстановить Брэда с жесткого диска:

 val q = db.query       
 q.constrain(classOf[Person])
 q.descend("name").constrain("Brad Pitt")           
 val brad = q.execute.get(0)                

См.список друзей еще раз ...

 brad.friends.foreach(println)

и BANG! NullPointerException !После небольшой отладки выясняется, что основное хранилище данных mutable.HashSet, на которое мы рассчитываем отслеживать друзей, определяется как transient в scala.collection.mutable.FlatHashTable :

@transient protected var table: Array[AnyRef] = new Array(initialCapacity) 

и, следовательно, когда мы говорим db4o о сохранении персоны, фактический список друзей не сериализуется.Кажется, что db4o должен использовать вместо readObject и writeObject методы HashSet.

Интересно, есть ли способ сказать db4o, чтобы сериализовать / десериализовать HashSet правильно илиесли есть более подходящая реализация Scala Set, которая подходит для db4o?

Ответы [ 2 ]

2 голосов
/ 21 октября 2010

Есть ли конкретная причина, по которой вам нужно использовать db4o?Как и во многих средах персистентности Java, предполагается, что изменчивость в объектах - это нормально, что на самом деле не слишком хорошо сочетается с идиоматическим Scala.

Возможно, вам больше понравится использование Squeryl или одного из нескольких хранилищ NoSQL, которые Akkaумеет иметь дело с.В отсутствие дополнительной информации, я бы, вероятно, рекомендовал Squeryl на этом этапе.

Сделав это, вы также захотите избежать двунаправленных дружеских отношений, сохраняющихся в ваших объектах Person - они будут делать неизменные "обновления" почти невозможно.Подъем этой информации в выделенный Relationship объект очень поможет, он также позволит вам легко добавлять больше информации о природе отношений по мере развития вашей системы.

Тогда ваш первоначальный вопрос станет неактуальным:)

0 голосов
/ 22 октября 2010

scala.collection.immutable.HashSet не страдает от той же проблемы сериализации, переписывание класса Person для использования неизменного HashSet решает проблему:

import scala.collection._ 

class Person (var name: String) { 
    private var _friends = new immutable.HashSet[Person] 

    def befriends     (p: Person) { _friends=_friends+p } 
    def fallsOutWith  (p: Person) { _friends=_friends-p } 
    def friends () = _friends
    override def toString = name 
} 
...