1

Я разрабатываю игру, которая хранит информацию в классе под названием WorldState. Каждый GameObject в мире (деревья, зомби, игрок, пакеты здоровья и т. Д.) Состоит из трех объектов: GameObjectController, GameObjectModel и GameObjectView. (Эти классы могут быть расширены, если GameObject требует дополнительных функций.)Является ли это хорошим интерфейсом для постоянного состояния?

WorldState имеет ссылку на реализацию интерфейса IPersistentState, который используется для загрузки и сохранения GameObjects. В настоящее время реализация IPersistentState - это ReadWriteXML, которая использует XML. Я боюсь, что интерфейс IPersistentState слишком связан с использованием XML - если бы я переключился на использование базы данных, или csv, или что-то еще, вероятно, это необходимо будет изменить. Я не думаю, что создаю достаточно абстракции.

IPersistentState интерфейс:

/// <summary> 
/// Used to read and write from persistent memory. 
/// 
/// When dictionaries are returned, they are key-value pairs: 
///  dict["key"] == value 
///  
/// Reading is done from whatever the current URI is. 
/// </summary> 
// This is too hard coded to XML. 
public interface IPersistentState 
{ 
    /// <summary> 
    /// Gets the KV for every object of element `elementName`. 
    /// Really this is just a convenience/wrapper method for `GetAllOfTypeIn()` 
    /// where the ancestor is the root. 
    /// </summary> 
    /// <param name="elementName">the element of object to get, like "zombie" or "point"</param> 
    /// <returns>(See interface summary) 
    ///    For Zombie, it could look like this: 
    /// 
    ///    dict["positionX"] == "23" 
    ///    dict["positionY"] == "4" 
    ///    
    ///    etc 
    /// </returns> 
    ICollection<IDictionary<string, string>> GetAllOfType(string elementName); 

    /// <summary> 
    /// Creates or overwrites the file `fileName`, filling it with the data in `dicts`. 
    /// The root of the data is `rootName`. 
    /// </summary> 
    /// <param name="dicts"></param> 
    /// <param name="rootName"></param> 
    /// <param name="fileName"></param> 
    void Write(ICollection<IDictionary<string, string>> dicts, string rootName, string fileName); 

    /// <summary> 
    /// Appends the information in `dict` to the end of the current file, under the element `elementName`. 
    /// </summary> 
    /// <param name="dict">The key-value pairs to append to the file identified by the current URI</param> 
    /// <param name="elementName">The root of the key-value pairs to append</param> 
    void Append(IDictionary<string, string> dict, string elementName); 

    /// <summary> 
    /// Sets the current URI from which to read. 
    /// </summary> 
    /// <param name="uri">Presumed to be in the Data/ directory.</param> 
    // not generic? 
    void SetURI(string uri); 

    /// <summary> 
    /// Gets the KV for every object of element `elementName`. 
    /// The search is constrainted to within `ancestor`. 
    /// </summary> 
    /// <param name="elementName">The element to look for</param> 
    /// <param name="ancestor">The element in which to search</param> 
    /// <returns>(See GetAllOfType)</returns> 
    ICollection<IDictionary<string, string>> GetAllTypeIn(string elementName, string ancestor); 
} 

Вот пример использования от метода WorldState загрузки:

 persistentState.SetURI(configURI); 
     ICollection<IDictionary<string, string>> levelVariantURIDicts = persistentState.GetAllOfType("levelVariant"); 

     // OH YEAH LINQ!! 
     levelVariantURIs = levelVariantURIDicts.Select(dict => dict["filePath"]).Distinct().ToList(); 

configURI указывает здесь:

<config> 
    <levelVariant> 
    <filePath>SampleVariant</filePath> 
    </levelVariant> 
    <levelVariant> 
    <filePath>LegendaryMode</filePath> 
    </levelVariant> 
    <levelVariant> 
    <filePath>AmazingMode</filePath> 
    </levelVariant> 
</config> 

Что вы об этом думаете? Возможно, абстракция не будет работать для базы данных, но она будет использоваться для разных типов файлов? Может быть, я просто надеюсь, что проект всегда использует XML? Как я могу изменить это, чтобы сделать его более общим?

ответ

1

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

Если вы хотите по-настоящему абстрактный интерфейс уровня доступа к данным, вам необходимо определить вашу модель, а затем создать свой интерфейс для вашей модели, а не для какой-либо конкретной реализации. Например, у вас есть rootName, fileName, elementName как параметры в ваших методах интерфейса, которые звучат так, будто вы думали о XML, когда вы его написали.

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

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

Так может быть, ваша модель имеет структуру, как:

Player 
    Player Attribute 
    Player Possessions 
    Player Score 
    City 
    Building 
     Objects 
     Immutable Object 
      Object property 
     Mutable Object 
      Object Property 
      Object Action 

и т.д.

Тогда ваши методы интерфейса должны использовать эти понятия.

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

void SavePlayerAttributes(string playerName, ICollection<IDictionary<string, string>> attributeNamesAndValues); 

или метод, чтобы создать новый объект в определенном месте:

void CreateImmutableObject(string cityName, string buildingName, ILocationCoordinates coordinates, IObjectPropertySet objectProperties); 

Очень грубый, но, надеюсь, вы получите эту идею.

0

Я склонен думать, текущая реализация хорошо сейчас, потому что:

  1. Трудно предвидеть изменения, которые вы будете делать в будущем, и вы, вероятно, более важные вещи, чтобы сосредоточиться на прямо сейчас чем преждевременные абстракции.
  2. У вас уже есть абстракция IPersistentState, поэтому, если вам нужно изменить реализацию позже, в то время это не должно быть слишком сложно.
  3. XML не обязательно является плохим форматом для других носителей информации. Например, это может быть вполне разумный формат для хранения в базе данных, если вы используете его только для сериализации/десериализации и не нуждаетесь в структурированных запросах внутри данных.