Skip to content

Latest commit

 

History

History
94 lines (70 loc) · 4.21 KB

GUIDELINES.md

File metadata and controls

94 lines (70 loc) · 4.21 KB

Overview

This document captures development standards and architecture decisions of this project as a point of reference.

Testing

Unsere Unittests nutzen das Kotest-Framework mit JUnit im Hintergrund. Dabei setzen wir auf WordSpec, da man damit semantisch übersichtlich sowohl einfache Tests als auch Behavior Driven Development umsetzen kann. Für Tests von Algorithmen ohne Logik/Verhalten kann auch FunSpec passend sein.

Viele Tests nutzen noch die StringSpec, welche jedoch schnell unübersichtlich wird, da sie keine Verschachtelung erlaubt. Im Server gibt es außerdem noch einige JUnit5-Tests. Diese sollten bei größeren Änderungen direkt zum neuen Stil migriert werden.

XStream

All network communication (client-server) is done via XML, in our JVM implementation the XStream library handles the serialization and deserialization from and to objects.

To implement the protocol properly it requires annotations. Apart from the persistent sdk protocol classes this is particularly relevant when implementing the Move and GameState classes in the current plugin, including all types used in their non-volatile fields (otherwise marked with @XStreamOmitField or transient), such as Board and Field.

Another common issue is the pollution of the XML with class attributes e.g. <lastMoveMono class="linked-hash-map"/>.
These are created by XStream to denote the implementation used for a Collection, if the field type is an abstract type such as List, Set, etc and it thus can't deduce the concrete implementation via reflection. To avert these superfluous attributes without needing a separate Converter, annotate the serialized fields with a concrete type instead. Ideally these fields should then be private with generically typed getters as to not expose the implementation details internally.

Cloning

Relevant discussion: #148

To enable cloning, we implement deep copy constructors together with a clone method which defers to the copy constructors. This is needed for all shared plugin classes that hold state and are not immutable. Small classes (such as Field) should be immutable, so they can be shared instead of cloning them.

It might be interesting to consider replacing cloning with implicit sharing/copy-on-write semantics to make search algorithms more efficient: https://doc.qt.io/qt-5/implicit-sharing.html#implicit-sharing-in-detail

ServiceLoader

We recently introduced the use of the Java built-in DI facility ServiceLoader to make some year-specific implementations from the plugin accessible in the sdk and server.

Currently there are two interfaces, IGamePlugin and XStreamProvider, which are implemented in the plugin and then loaded through a ServiceLoader. The information which implementations to use resides in resources/META-INF/services.

Networking Protocol Classes

ProtocolPacket is the common interface for objects sent via the XML Protocol.

  • are all suffixed with Request
  • ask for an action or information
  • any request that extends AdminLobbyRequest requires authentication beforehand

(*Response) Response to a request
(*Event) Update to all observers

Data sent to a specific room has to implement RoomMessage and is then wrapped in a RoomPacket.

The package contains a few standard messages, but most will be implemented in the corresponding plugin.