Сохранение кода на одном уровне при работе со статическими методами - PullRequest
3 голосов
/ 16 августа 2010

Это может быть немного субъективно, но я бы хотел узнать ваше мнение о моей текущей ситуации. У меня есть класс, который будет использоваться для сериализации / десериализации объекта.

public class MyClass
{
    public static string ToXmlString( MyClass c ) { /*...*/ }
    public static MyClass FromXmlString( string xml ) { /*...*/ }
}

Мне нравится этот подход, потому что он поддерживает две функции на одном уровне. Однако моя цель - избегать использования статических методов (когда это возможно). Мне также кажется, что я мог бы испортить SRP, но главная цель этого объекта в том, что его можно сериализовать / десериализовать из строки XML.

Есть мысли об использовании статических методов в этой ситуации? Должен ли я просто сделать ToXmlString нестатичным, но оставить FromXmlString статичным? Должен ли я создать новый класс, который будет обрабатывать только сериализацию MyClass?

РЕДАКТИРОВАТЬ:

Класс, который я здесь обсуждаю, является простым объектом переноса. Он используется для сохранения / восстановления значений из стороннего инструмента.

Спасибо!

Ответы [ 6 ]

2 голосов
/ 16 августа 2010

FWIW Я думаю, что сериализация - это проблема, которая должна быть отделена от остальной части вашего класса, прежде всего, если ваш класс является бизнес-типом.

Общее правило при разработке компонента заключается в том, чтобы гарантировать, что он решает только несколько проблем, и отделить проблемы бизнеса от технических.

Что если позже вам понадобится управлять сериализацией из базы данных или двоичного формата?

Вы можете закончить все большим количеством технических методов (SaveToDB, LoadFromDB, ToBinaryStream, FromBinaryStream ...), которые будут загромождать ваш класс и усложнять его обслуживание, скрывая его основные цели (например, бизнес). 1007 *

1 голос
/ 24 августа 2010

В стандартных библиотеках для C # и Java принято, что методы To__ являются методами экземпляров, а методы From__ являются статическими (по необходимости). Например: ToString() - это метод экземпляра.

0 голосов
/ 16 августа 2010

Вы можете определить конструктор, который принимает XMLReader (или строку, если вы действительно настаиваете).Основным преимуществом этого является то, что он позволяет вам иметь более сильные инварианты в вашем классе и быть явным в отношении любых неизменных членов с помощью readonly.

0 голосов
/ 16 августа 2010

Я не думаю, что слишком страшно разделять дополнительные методы по отношению к статическому и экземпляру, так как Framework иногда делает это (например String.Split / Join).

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

Чистая статическая функция может быть более удобной в обслуживании, чем метод экземпляра, поскольку метод экземпляра не сообщает очевидным образом, какие поля экземпляра он может изменять. Следуя правилу, согласно которому статическое состояние не поддерживается, можно полагаться на статический метод, работающий только с его параметрами, и, таким образом, роль метода в приложении можно лучше прогнозировать. Это особенно важно при многопоточности.

Поскольку метод ToXmlString применяется к экземпляру класса, в котором он определен, некоторые из этих соображений неприменимы. Он может легко изменить состояние объекта, который ему передается скрытно, так как он может получить доступ ко всем закрытым членам экземпляра. Но я просто хочу сказать, что, как правило, статические методы не являются проблемой.

0 голосов
/ 16 августа 2010

Обрабатывая ответ Бенуа, вот пример, где сериализуемый класс определяет поведение сериализации (я не писал это):

// : c12:SerialCtl.java
// Controlling serialization by adding your own
// writeObject() and readObject() methods.
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerialCtl implements Serializable {
  private String a;

  private transient String b;

  public SerialCtl(String aa, String bb) {
    a = "Not Transient: " + aa;
    b = "Transient: " + bb;
  }

  public String toString() {
    return a + "\n" + b;
  }

  private void writeObject(ObjectOutputStream stream) throws IOException {
    stream.defaultWriteObject();
    stream.writeObject(b);
  }

  private void readObject(ObjectInputStream stream) throws IOException,
      ClassNotFoundException {
    stream.defaultReadObject();
    b = (String) stream.readObject();
  }

  public static void main(String[] args) throws IOException,
      ClassNotFoundException {
    SerialCtl sc = new SerialCtl("Test1", "Test2");
    System.out.println("Before:\n" + sc);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    ObjectOutputStream o = new ObjectOutputStream(buf);
    o.writeObject(sc);
    // Now get it back:
    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
        buf.toByteArray()));
    SerialCtl sc2 = (SerialCtl) in.readObject();
    System.out.println("After:\n" + sc2);
  }
}

Обратите внимание на использование переходного процесса для описания полей, которые не будут сериализованы.

0 голосов
/ 16 августа 2010

Если вы хотите стандартную сериализацию (XML или нет), оба метода сериализации / десериализации не должны быть статическими.

В MyClass вы должны переопределить "writeObject" и "readObject", чтобы заменить методы сериализации по умолчанию вашими. Вот Sun учебник о тезисах.

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

PS: это не вопрос, но если вы хотите сериализацию WML, вы можете использовать XStream API .

...