Czysta domena, a optimistic locking

0

Cześć,

chciałem się dowiedzieć w jaki sposób implementujecie u siebie optimistic locking. Chciałbym, żeby (jako detal implementacyjny) optimistic locking był w całości obsłużony w warstwie infrastruktury, co oznacza dla mnie, że żadne pole (klasyczne version) nie powinno wchodzić głębiej.

Kończy się to u mnie dosyć skomplikowanymi konstruktami w implementacji repozytorium, tutaj przykład w Kotlinie:

class Repository {

    fun updateById(id: String, update: (Domain) -> Domain): UpdateResult {
        val documentToUpdate = findToUpdate() ?: return NothingToUpdateFound
        val updated = update(documentToUpdate.toDomain())
        val newDocument = Document.from(updated, updatedAt = clock.instant())

        val updatedDocument = findAndReplace(
            where(ID).isEqualTo(id).and(UPDATED_AT).isEqualTo(documentToUpdate.updatedAt),
            newDocument
        )

        if(updatedDocument == null) {
            return OptimisticLocking
        }

        return Updated(updatedDocument)
    }

}

Przykład trochę uproszczony, ale chcę pokazać zasadę. Najbardziej nie podoba mi potrzeba przekazania funkcji, ale chyba tego nie uniknę (chyba, że macie jakieś pomysły)

To co lubię w tym podejściu:

  • Całość jest obsłużona na poziomie infrastruktury

To czego nie lubię:

  • Nie mogę klasycznie korzystać z repozytorium w stylu:
    val obj = repository.findById(ID)
    obj.setX(3)
    repository.save(obj)
    
0

@mythflame:

Ciekawy temat wywlokłeś. W moich oczach 'version' jest polem, które długotrwale wędruje po sesji użytkownika, aż do (próby) zapisu.
Nie wyobrażam sobie, żeby go nie było.

Pewnie może być chronione, na pewno nie wypuszczane na UI, ale MSZ nie może go nie być

mythflame napisał(a):

To czego nie lubię:

  • Nie mogę klasycznie korzystać z repozytorium w stylu:
    val obj = repository.findById(ID)
    obj.setX(3)
    repository.save(obj)
    

Nie tylko "nie mogę" czy "nie lubię", ale tego nie wyobrażam sobie w złożonym biznesie (system kadrowo-płacowy na Polskę).

mythflame napisał(a):

Chciałbym, żeby (jako detal implementacyjny) optimistic locking był w całości obsłużony w warstwie infrastruktury, co oznacza dla mnie, że żadne pole (klasyczne version) nie powinno wchodzić głębiej.

A właściwie dlaczego? Dla szlachetnej walki?
Model obiektowy a model bazodanowy ma NIEJEDEN konflikt swoich podstawowych idei, a w/w zagadnienie to przy nich nieistotny detal.

0
ZrobieDobrze napisał(a):

Ciekawy temat wywlokłeś. W moich oczach 'version' jest polem, które długotrwale wędruje po sesji użytkownika, aż do (próby) zapisu.
Nie wyobrażam sobie, żeby go nie było.

Co to znaczy po sesji użytkownika? U mnie konkretnie użytkownik zgłasza jakieś dane do formularza. Chciałbym uniknąć sytuacji, w której zostaną one nadpisane równolegle przez np. jakiś proces w tle albo admina. Zamiast tego prawdopodobnie wolałbym powtórzyć zapis.
W moim przykładzie pole "version" jest potrzebne jedyne do tego, żeby zapobiec równoległym zapisom.

Nie tylko "nie mogę" czy "nie lubię", ale tego nie wyobrażam sobie w złożonym biznesie (system kadrowo-płacowy na Polskę).

Tego nie rozumiem :/ Nie wyobrażasz sobie odczytania danych z bazy, a później ich zapisania?

mythflame napisał(a):

Chciałbym, żeby (jako detal implementacyjny) optimistic locking był w całości obsłużony w warstwie infrastruktury, co oznacza dla mnie, że żadne pole (klasyczne version) nie powinno wchodzić głębiej.

A właściwie dlaczego? Dla szlachetnej walki?
Model obiektowy a model bazodanowy ma NIEJEDEN konflikt swoich podstawowych idei, a w/w zagadnienie to przy nich nieistotny detal.

Tylko dlatego, żeby mój model był prostszy i przedstawiał rzeczywiście to co ma przedstawiać. Żebym wchodząc w ten kod nie widział technicznych pól, które mogą zaciemniać biznes. Ale może to jest bezsensowna walka, dlatego podrzuciłem ten wątek ;)

0

@mythflame: no to wrzucasz sobie na liste id tego formularza, kto i kiedy zalozyl locka. A potem na poziomie infry, operacje które modyfikują sprawdzasz czy jest zalozny lock jesli nie wyjebujesz blad jak jest lock to czy ten lock jest dla usera ktory wykonuje operacje jesli tak to puść wykonywanie logiki biznesowej. Ja mam sprawdzanie locków zrobione na poziomie mojego inmemory command bus'a który nie pozwala wrzucic mi komendy która narusza locki.

0
mythflame napisał(a):
ZrobieDobrze napisał(a):

Ciekawy temat wywlokłeś. W moich oczach 'version' jest polem, które długotrwale wędruje po sesji użytkownika, aż do (próby) zapisu.
Nie wyobrażam sobie, żeby go nie było.

Co to znaczy po sesji użytkownika? U mnie konkretnie użytkownik zgłasza jakieś dane do formularza. Chciałbym uniknąć sytuacji, w której zostaną one nadpisane równolegle przez np. jakiś proces w tle albo admina. Zamiast tego prawdopodobnie wolałbym powtórzyć zapis.
W moim przykładzie pole "version" jest potrzebne jedyne do tego, żeby zapobiec równoległym zapisom.

Dokładnie. Użyłem słowa "sesja" w sensie czasu, jak długo użytkownik siedzi na obiektem, ile czasu / przez ile warstw programu to by nie przechodziło.

A że do optimistiku trzeba "version", to oczywistość.

Ja nie mam mentalnego problemu z "ukrytymi" polami, tzn takimi jakich nie widzi user, czy o jakich nie mówi ekspert domenowy (nie będący softwarowcem)
Np "Id" (klasyczny klucz pierwotny) czy "UUID" (alternatywna realizacja tożsamości obiektu). Dopisz "version" do tej listy, dla mnie to jest dokładnie ta sama grupa.

@Schadoow:

dzięki za wspomnienie o "id" ... czyli tez nie masz czystej domeny ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1