Apa alasan untuk membuat subtipe Berat yang berbeda? Saya melihat pengembang kami membuat subtipe NetWeight dan GrossWeight sebagai Objek Nilai. Keduanya memiliki implementasi yang sama. Apakah ada nilai di dalamnya? Mengapa tidak menggunakan tipe nilai Bobot untuk kedua skenario? Saya merasa itu benar-benar salah, ingin mendengar pendapat ahli tentang ini ... Jika Anda merasa itu salah, bagaimana Anda menjelaskan mengapa itu salah?

public struct NetWeight : IEquatable<NetWeight>
{
    private const string DefaultMeasurementUnit = "kg";

    public double Value { get; }
    public string MeasurementUnit { get; }

    public NetWeight(double value, string measurementUnit)
    {
        if (value < 0) throw new BusinessRuleValidationException("NetWeight value can't be negative");
        if (string.IsNullOrWhiteSpace(measurementUnit)) throw new BusinessRuleValidationException("NetWeight measurement unit can't be null or whitespace");

        Value = value;
        MeasurementUnit = measurementUnit.Trim();
    }

    public override string ToString()
    {
        return $"{Value}{MeasurementUnit}";
    }
    public static NetWeight operator +(NetWeight left, NetWeight right)
    {
        if (left.MeasurementUnit != right.MeasurementUnit) throw new ArgumentException("Measurement units are not the same");

        return new NetWeight(left.Value + right.Value, left.MeasurementUnit);
    }
    public static NetWeight operator -(NetWeight left, NetWeight right)
    {
        if (left.MeasurementUnit != right.MeasurementUnit) throw new ArgumentException("Measurement units are not the same");

        return new NetWeight(left.Value - right.Value, left.MeasurementUnit);
    }
    public static NetWeight operator *(NetWeight left, Quantity right)
    {
        if (left.MeasurementUnit != right.MeasurementUnit) throw new ArgumentException("Measurement units are not the same");
        return new NetWeight(left.Value * right.Value, left.MeasurementUnit);
    }
    public static NetWeight operator *(Quantity left, NetWeight right)
    {
        if (left.MeasurementUnit != right.MeasurementUnit) throw new ArgumentException("Measurement units are not the same");
        return new NetWeight(left.Value * right.Value, left.MeasurementUnit);
    }

    // TODO: come up with a refactoring that prevents the use of primitive types
    public static NetWeight operator *(NetWeight left, int right)
    {
        return new NetWeight(left.Value * right, left.MeasurementUnit);
    }


    #region IEquatable
    public override bool Equals(object obj)
    {
        return obj is NetWeight weight && Equals(weight);
    }
    public bool Equals(NetWeight other)
    {
        return Value == other.Value &&
               MeasurementUnit == other.MeasurementUnit;
    }
    public override int GetHashCode()
    {
        return HashCode.Combine(Value, MeasurementUnit);
    }
    public static bool operator ==(NetWeight left, NetWeight right)
    {
        return left.Equals(right);
    }
    public static bool operator !=(NetWeight left, NetWeight right)
    {
        return !(left == right);
    }
    #endregion 
}
1
DmitriBodiu 19 September 2019, 17:42

1 menjawab

Jawaban Terbaik

Apa alasan untuk membuat subtipe Berat yang berbeda?

Jika GrossWeight dan NetWeight adalah ide berbeda yang berbeda di domain Anda, jika itu akan menjadi kesalahan untuk mengganti berat kotor dengan berat bersih, dan jika Anda menggunakan bahasa yang akan menandai jenis yang tidak kompatibel, maka menetapkan GrossWeight dan NetWeight sebagai jenis yang berbeda memungkinkan Anda menggunakan pemeriksa tipe bahasa itu sendiri untuk menandai (dan dengan demikian menghilangkan) kelas kesalahan tertentu yang mungkin lolos ke produksi.

Fakta bahwa dua jenis bobot yang berbeda saat ini memiliki implementasi yang setara pada dasarnya merupakan kecelakaan implementasi. Dalam bahasa yang mendukungnya, Anda dapat mempertimbangkan agar kedua tipe tersebut mewarisi implementasinya dari beberapa nenek moyang yang sama.

Banyak model akan memperlakukan pengidentifikasi menggunakan pola yang serupa -- meskipun pada tingkat implementasi tidak ada perbedaan, akan berguna untuk membedakan jenis CustomerId dari jenis OrderId untuk memastikan bahwa Anda tidak merusak kumpulan data Anda dengan secara tidak sengaja mengganti yang satu dengan yang lain.

Tempat lain di mana Anda akan melihat pendekatan ini adalah dalam model yang membedakan input tidak tepercaya dari data tepercaya. Tentu, representasi primitif yang mendasarinya adalah "hanya byte", tetapi memungkinkan Anda untuk memanfaatkan sistem tipe untuk membedakan data yang telah melewati pos pemeriksaan validasi dari data yang belum.

2
VoiceOfUnreason 19 September 2019, 16:09