Сохранение кода на одном уровне при работе со статическими методами

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

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

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

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

ИЗМЕНИТЬ:

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

Спасибо!


person Jerod Houghtelling    schedule 16.08.2010    source источник
comment
Я избегаю статики по ряду мелких причин. 1) Легче перейти к IoC, если это необходимо 2) Расширить объекты за счет наследования 3) Избежать деградации до классов Бога, используя практики ООП...   -  person Jerod Houghtelling    schedule 16.08.2010


Ответы (6)


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

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

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

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

person Pragmateek    schedule 16.08.2010

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

person munificent    schedule 23.08.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);
  }
}

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

person Amir Afghani    schedule 16.08.2010

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

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

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

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

person Benoit Courtine    schedule 16.08.2010
comment
реальная сериализация? Ты имеешь в виду, что то, что сейчас есть у Джерода, не реально? Есть множество вполне веских причин не использовать стандартные механизмы сериализации. - person Nikita Rybak; 16.08.2010
comment
Ты прав. Стандартный мир лучше, чем реальный: я отредактировал свой пост, чтобы исправить это, спасибо. - person Benoit Courtine; 16.08.2010

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

person Jon Hanna    schedule 16.08.2010

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

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

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

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

person Jeffrey L Whitledge    schedule 16.08.2010