Структура пакета для проекта Java?

Q. Почему я должен выбрать этот ответ?
  • Выберите этот ответ, если вы хотите, чтобы с максимальной скоростью .NET был способен.
  • Игнорируйте этот ответ, если хотите действительно, очень легко метод клонирования.

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

в 10 раз быстрее, чем другие методы

Следующий метод выполнения глубокого клона:

  • в 10 раз быстрее, чем что-либо, что предполагает сериализацию / десериализацию; g12]
  • Довольно близко к теоретической максимальной скорости, на которую способен .NET.

И метод ...

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

Обратите внимание, что если вы используете Nested MemberwiseClone для глубокой копии вам нужно вручную реализовать ShallowCopy для каждого вложенного уровня в классе и DeepCopy, который вызывает все указанные методы ShallowCopy для создания полного клона. Это просто: всего несколько строк, см. Демо-код ниже.

Вот результат кода, показывающий относительную разницу в производительности для 100 000 клонов:

  • 1.08 секунд для Nested MemberwiseClone на вложенных структурах
  • 4.77 секунд для вложенных MemberwiseClone на вложенных классах
  • 39.93 секунд для сериализации / десериализации

Использование вложенного члена в классе почти так же быстро, как копирование структуры, а копирование структуры довольно близко к теоретической максимальной скорости, на которую способен .NET.

Demo 1 of shallow and deep copy, using classes and MemberwiseClone:
  Create Bob
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Clone Bob >> BobsSon
  Adjust BobsSon details
    BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Elapsed time: 00:00:04.7795670,30000000

Demo 2 of shallow and deep copy, using structs and value copying:
  Create Bob
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Clone Bob >> BobsSon
  Adjust BobsSon details:
    BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Elapsed time: 00:00:01.0875454,30000000

Demo 3 of deep copy, using class and serialize/deserialize:
  Elapsed time: 00:00:39.9339425,30000000

Чтобы понять, как сделать глубокую копию, используя MemberwiseCopy , вот демонстрационный проект, который использовался для генерации времени выше:

// Nested MemberwiseClone example. 
// Added to demo how to deep copy a reference class.
[Serializable] // Not required if using MemberwiseClone, only used for speed comparison using serialization.
public class Person
{
    public Person(int age, string description)
    {
        this.Age = age;
        this.Purchase.Description = description;
    }
    [Serializable] // Not required if using MemberwiseClone
    public class PurchaseType
    {
        public string Description;
        public PurchaseType ShallowCopy()
        {
            return (PurchaseType)this.MemberwiseClone();
        }
    }
    public PurchaseType Purchase = new PurchaseType();
    public int Age;
    // Add this if using nested MemberwiseClone.
    // This is a class, which is a reference type, so cloning is more difficult.
    public Person ShallowCopy()
    {
        return (Person)this.MemberwiseClone();
    }
    // Add this if using nested MemberwiseClone.
    // This is a class, which is a reference type, so cloning is more difficult.
    public Person DeepCopy()
    {
            // Clone the root ...
        Person other = (Person) this.MemberwiseClone();
            // ... then clone the nested class.
        other.Purchase = this.Purchase.ShallowCopy();
        return other;
    }
}
// Added to demo how to copy a value struct (this is easy - a deep copy happens by default)
public struct PersonStruct
{
    public PersonStruct(int age, string description)
    {
        this.Age = age;
        this.Purchase.Description = description;
    }
    public struct PurchaseType
    {
        public string Description;
    }
    public PurchaseType Purchase;
    public int Age;
    // This is a struct, which is a value type, so everything is a clone by default.
    public PersonStruct ShallowCopy()
    {
        return (PersonStruct)this;
    }
    // This is a struct, which is a value type, so everything is a clone by default.
    public PersonStruct DeepCopy()
    {
        return (PersonStruct)this;
    }
}
// Added only for a speed comparison.
public class MyDeepCopy
{
    public static T DeepCopy(T obj)
    {
        object result = null;
        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;
            result = (T)formatter.Deserialize(ms);
            ms.Close();
        }
        return (T)result;
    }
}

Затем вызовите демо из основного:

void MyMain(string[] args)
{
    {
        Console.Write("Demo 1 of shallow and deep copy, using classes and MemberwiseCopy:\n");
        var Bob = new Person(30, "Lamborghini");
        Console.Write("  Create Bob\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
        Console.Write("  Clone Bob >> BobsSon\n");
        var BobsSon = Bob.DeepCopy();
        Console.Write("  Adjust BobsSon details\n");
        BobsSon.Age = 2;
        BobsSon.Purchase.Description = "Toy car";
        Console.Write("    BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
        Console.Write("  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
        Debug.Assert(Bob.Age == 30);
        Debug.Assert(Bob.Purchase.Description == "Lamborghini");
        var sw = new Stopwatch();
        sw.Start();
        int total = 0;
        for (int i = 0; i < 100000; i++)
        {
            var n = Bob.DeepCopy();
            total += n.Age;
        }
        Console.Write("  Elapsed time: {0},{1}\n\n", sw.Elapsed, total);
    }
    {               
        Console.Write("Demo 2 of shallow and deep copy, using structs:\n");
        var Bob = new PersonStruct(30, "Lamborghini");
        Console.Write("  Create Bob\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
        Console.Write("  Clone Bob >> BobsSon\n");
        var BobsSon = Bob.DeepCopy();
        Console.Write("  Adjust BobsSon details:\n");
        BobsSon.Age = 2;
        BobsSon.Purchase.Description = "Toy car";
        Console.Write("    BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
        Console.Write("  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);                
        Debug.Assert(Bob.Age == 30);
        Debug.Assert(Bob.Purchase.Description == "Lamborghini");
        var sw = new Stopwatch();
        sw.Start();
        int total = 0;
        for (int i = 0; i < 100000; i++)
        {
            var n = Bob.DeepCopy();
            total += n.Age;
        }
        Console.Write("  Elapsed time: {0},{1}\n\n", sw.Elapsed, total);
    }
    {
        Console.Write("Demo 3 of deep copy, using class and serialize/deserialize:\n");
        int total = 0;
        var sw = new Stopwatch();
        sw.Start();
        var Bob = new Person(30, "Lamborghini");
        for (int i = 0; i < 100000; i++)
        {
            var BobsSon = MyDeepCopy.DeepCopy(Bob);
            total += BobsSon.Age;
        }
        Console.Write("  Elapsed time: {0},{1}\n", sw.Elapsed, total);
    }
    Console.ReadKey();
}

Снова обратите внимание, что если вы используете Вложенный объект MemberwiseClone для глубокой копии вам нужно вручную реализовать ShallowCopy для каждого вложенного уровня в классе, а DeepCopy, который вызывает все указанные методы ShallowCopy для создания полного clo северо-восток Это просто: всего несколько строк, см. Демонстрационный код выше.

Типы значений и ссылки Типы

Обратите внимание, что когда дело доходит до клонирования объекта, существует большая разница между «структурой» и «классом»:

  • Если у вас есть «структура», это тип значения, поэтому вы можете просто скопировать его, и содержимое будет клонировано ( но он будет делать только мелкий клон, если вы не используете методы в этом сообщении).
  • Если у вас есть «класс», это ссылочный тип, поэтому, если вы его скопируете, все, что вы делаете, это копирование указатель на него. Чтобы создать настоящий клон, вы должны быть более креативными и использовать различия между типами значений и типами ссылок , которые создают другую копию исходного объекта в памяти.

См. различия между типами значений и типами ссылок .

Контрольные суммы для облегчения отладки

  • Неправильное клонирование объектов может привести к очень сложным, выпадающие ошибки. В производственном коде я стараюсь реализовать контрольную сумму, чтобы дважды проверить, что объект был клонирован правильно и не был поврежден другой ссылкой на него. Эта контрольная сумма может быть отключена в режиме деблокирования.
  • Я нахожу этот метод весьма полезным: часто вы хотите клонировать части объекта, а не все.

Действительно полезно для развязки многих потоков из многих других потоков

. Один превосходный вариант использования этого кода - это подача клонов вложенного класса или структуры в очередь для реализации шаблона производителя / потребителя.

  • Мы можем иметь одну (или более) нити, модифицирующую класс, который у них есть, затем нажатие полной копии этого класса на ConcurrentQueue.
  • Затем мы имеем (или более) потоков, вытягивающих копии этих классов и имеющих дело с ними.

Это на практике очень хорошо работает и позволяет отделить множество потоков (производителей) от одного или нескольких потоки (потребители).

И этот метод также близок быстро: если мы используем вложенные структуры, это на 35 раз быстрее, чем сериализация / десериализация вложенных классов, и позволяет нам использовать преимущества всех потоков, доступных на машина.

Обновить

По-видимому, ExpressMapper работает так же быстро, если не быстрее, чем ручное кодирование, например, выше. Возможно, мне придется посмотреть, как они сравниваются с профилировщиком.

104
задан Jonik 22 May 2009 в 10:49
поделиться

4 ответа

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

83
ответ дан johnstok 24 November 2019 в 04:00
поделиться

Существует несколько существующих ресурсов, которые Вы могли бы проверить:

  1. Правильно Упаковывают Ваши Классы Java
  2. архитектура Spring 2.5
  3. Учебное руководство по Java - Именование Пакета
  4. Соглашения о присвоении имен SUN

Если это имеет значение, мои собственные персональные инструкции, которые я склонен использовать, следующие:

  1. Запускаются с обратного домена, например, "com.mycompany".
  2. название продукта Использования, например, "myproduct". В некоторых случаях я склонен иметь общие пакеты, которые не принадлежат конкретному продукту. Они закончились бы категоризированные согласно функциональности этих общих классов, например, "io", "util", "ui", и т.д.
  3. После этого это становится большей свободной формой. Обычно я группируюсь согласно проекту, области функциональности, развертывания, и т.д. Например, у меня мог бы быть "project1", "project2", "ui", "клиент", и т.д.

Несколько других точек:

  1. Это довольно распространено в проектах, я продолжил работать для имен пакета, чтобы вытекать из проектной документации. Обычно продукты уже разделены на области функциональности или цели.
  2. не подчеркивают слишком много о продвижении общей функциональности в более высокие пакеты сразу же. Ожидайте там, чтобы быть потребностью через проекты, продукты, и т.д., и затем осуществить рефакторинг.
  3. зависимости межпакета Часов. Они не все плохи, но это может показать плотное соединение между тем, что могло бы быть отдельными единицами. Существуют инструменты, которые могут помочь Вам отслеживать это.
55
ответ дан user151019 24 November 2019 в 04:00
поделиться

Путем у меня обычно есть своя иерархия папки -

  • Название проекта
    • мусорное ведро src
    • , тесты
    • освобождают
    • документы
1
ответ дан pdeva 24 November 2019 в 04:00
поделиться

Я бы посоветовал создавать структуру вашего пакета по функциям, а не по уровню реализации. Хорошая статья об этом - Практики Java: Пакет за функцией, а не уровень

42
ответ дан 24 November 2019 в 04:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: