Wskazówki dotyczące nazywania niewygodnych obiektów specyficznych dla domeny?

12

Modeluję układ chemiczny i mam problemy z nazywaniem moich elementów / przedmiotów w wyliczeniu.

Nie jestem pewien, czy powinienem użyć:

  • wzór atomowy
  • nazwa chemiczna
  • skrócona nazwa chemiczna.

Na przykład kwasem siarkowym jest H2SO4, a kwasem chlorowodorowym jest HCl.

W przypadku tych dwóch prawdopodobnie użyłbym wzoru atomowego, ponieważ są one dość powszechne.

Mam jednak inne, takie jak heksafluorokrzemian sodu, którym jest Na2SiF6.

W tym przykładzie, wzór atomowej nie jest oczywiste, (mi), ale nazwa chemiczna to brzydko długi: myEnum.SodiumHexaFluoroSilicate. Nie jestem pewien, jak mógłbym bezpiecznie wymyślić skróconą nazwę chemiczną, która miałaby spójny wzór nazewnictwa.

Jest kilka problemów, które próbuję rozwiązać, nazywając elementy wyliczeniowe.
Pierwszą jest czytelność, przy czym dłuższe nazwy stanowią problem.
Druga to łatwość pobrania kodu dla nowych opiekunów, a tutaj krótsze nazwy stanowią problem.
Kolejną kwestią jest to, że właściciele firm zwykle odnoszą się do pełnej nazwy chemicznej, ale nie zawsze. „Kęski” chemikalia są określane przez ich formułę.
Ostatnim problemem jest upewnienie się, że jest spójny. Nie chcę mieszanej konwencji nazewnictwa, ponieważ nie będzie możliwe zapamiętanie, którego użyć.

Z punktu widzenia konserwacji, które z powyższych opcji nazewnictwa wolisz zobaczyć i dlaczego?


Uwaga: wszystko tutaj poniżej linii ma charakter uzupełniający | materiał wyjaśniający. Nie daj się w to wciągnąć. Główne pytanie dotyczy nazywania niezręcznych obiektów.

Opcja atomowa

public myEnum.ChemTypes
{  
   H2SO4,
   HCl,
   Na2SiF6
}

Opcja nazwy chemicznej

public myEnum.ChemTypes
{
   Kwas Siarkowy,
   Kwas chlorowodorowy,
   Heksafluorokrzemian sodu  
}

Oto kilka dodatkowych szczegółów z komentarzy do tego pytania:

  • Odbiorcami kodu będą tylko programiści, a nie chemicy.
  • Używam C #, ale myślę, że to pytanie jest bardziej interesujące, gdy ignoruję język implementacji.
  • Zaczynam od 10 - 20 związków i miałbym co najwyżej 100 związków, więc nie muszę się martwić o każdy możliwy związek. Na szczęście jest to domena stała.
  • Wyliczenie służy jako klucz do wyszukiwania w celu ułatwienia powszechnych / ogólnych obliczeń chemicznych - co oznacza, że ​​równanie jest takie samo dla wszystkich związków, ale wstawiasz właściwość związku, aby uzupełnić równanie.

Przykładowa funkcja może wyglądać następująco:

public double GetMolesFromMass (double mass_grams, myEnum.ChemTypes chem)
{
  double molarWeight = MolarWeightLookupFunctionByChem (chem); // zwraca gram / mol
  podwójne mole = masa / masa molowa; // konwertuje na mole

  mole zwrotne;
}

// Przykładowe wywołanie:
myMoles = GetMolesFromMass (1000, myEnum.ChemTypes.Na2SiF6);
//*lub*
myMoles = GetMolesFromMass (1000, myEnum.ChemTypes.SodiumHexafluorosilicate);
public double GetSpecificGravity (myEnum.ChemTypes chem, double conc)
{
  // oblicza ciężar właściwy związku chemicznego na podstawie stężenia
  double sg = SpecificGravityLookupTableByChem (chem, conc);  
}

Zatem wyliczenie nazwy związku jest używane jako klucz i dla zapewnienia spójności w odniesieniu do związku z powiązanymi funkcjami.


źródło
7
dlaczego muszą być enum? istnieje nieskończona ilość możliwych związków, więc nigdy nie będziesz w stanie ustawić ich wszystkich
maniak ratchet
3
Jako programista, a nie chemik, uważam, że Na2SiF6 i heksafluorokrzemian sodu są równie niejasne. Ten pierwszy jest krótszy do wpisania i najprawdopodobniej przekroczy dziwne reguły kodowania według identyfikatora nie więcej niż 40 znaków.
mouviciel,
5
Jako programista osobiście uważam, że Sodium stoczy mi się z palców szybciej niż Na2 - słowa mają tendencję do łatwiejszego pływania podczas pisania (z tego powodu nienawidzę notacji węgierskiej).
Drake Clarris,
5
Nie powinny być wartościami wyliczeniowymi, powinny być instancjami o Substancedowolnych potrzebnych właściwościach.
AakashM,
2
@ GlenH7: po prostu przeczytaj swoje pytanie na temat „meta”. Myślę, że prawdziwym problemem tutaj dla niektórych ludzi jest „dlaczego nazwy chemiczne w ogóle muszą być w kodzie”? Posiadanie tych nazw tylko jako pewnej formy danych pozwoliłoby uniknąć zaśmiecania kodu bardzo długimi nazwami, i można wybrać takie nazwy, jakie preferuje użytkownik systemu, niezależnie od tego, co deweloper może o nich pomyśleć. To przekazałoby odpowiedzialność za nazewnictwo użytkownikowi i całkowicie uniknęłoby problemu.
Doc Brown

Odpowiedzi:

9

Kiedy zacząłem przepisywać mój obecny projekt ze spaghetti na rozsądny kod, stanąłem przed tym samym problemem. Moja domena problemowa ma charakter medyczny i zamiast używać nazw takich jak „ETCO2” i „SPO2” dla moich wyliczeń, użyłem pełnych angielskich nazw.

Z jednej strony bardzo przydatne było posiadanie angielskich nazw, gdy byłem nowy w dziedzinie problemów. Z drugiej strony, odkąd pracuję z tymi terminami od roku, stwierdzam, że pełne angielskie nazwy są zdecydowanie zbyt szczegółowe i znam wystarczająco dobrze terminy, których wolałbym używać skrótów.

Moją radą byłoby użycie wzoru atomowego i dołączenie komentarza do każdej wartości wyliczeniowej, która daje jej pełną nazwę, przy założeniu, że każdy, kto patrzy na twój kod, będzie albo a) chemikiem, albo b) pracujący nad kodem wystarczająco długo że w naturalny sposób zapoznają się z formułami.

Mrówka
źródło
1
+1: Poza tym zawsze można wyszukać „ETCO2” lub „Na2SiF6” i gotowe.
Steven Evers,
5

Kto jest odbiorcą kodu? Czy chemicy będą używać Enums, czy tylko programiści bez specjalnego szkolenia w dziedzinie chemii?

Jeśli chemicy będą używać kodu, zapytaj ich. Bardzo prawdopodobne, że wolą skrócone symbole, ponieważ mogą je łatwo rozpoznać. Jeśli programiści wiedzy ogólnej będą używać tych identyfikatorów w imieniu chemików, myślę, że lepiej jest używać wersji angielskich.

Robert Harvey
źródło
będą tylko programiści, a nie chemicy
1
lub dodaj tłumaczenie do dokumentacji każdego enum
ratchet maniaka
4

Nie ma powodu, aby nie łączyć „wszystkich powyższych”.

Problem z pełnymi nazwami polega na tym, że pisanie będzie uciążliwe, problemem z nazwami symboli jest brak znaczenia.

Utwórz stałe wartości o pełnej nazwie. Następnie utwórz definicje związane ze stałą. Następnie możesz łatwo tworzyć nowe, krótsze definicje, gdy bardziej zaznajomisz się ze znaczeniem skrótu.

const int SodiumHexaFluoroSilicate = 16893859;   
const float Gold = 196.966569;

#define SoduimSilicate SodiumHexaFluoroSilicate 
#define F6Na2Si SodiumHexaFluoroSilicate 
#define au Gold 
Daniel
źródło
Użyłem zakorkowanej próbki kodu C ... Myślę, że powinno to być łatwe do przetłumaczenia na język C #.
Daniel
Nie martwię się tak bardzo o konkretną implementację, dlatego nie podałem C # w moim pytaniu. I podobała mi się twoja sugestia z punktu widzenia C. Tag C # Description z System.ComponentModel to elegancki sposób na dodanie deskryptora. Bardziej interesowała mnie szersza odpowiedź na pytanie dotyczące konkretnego wdrożenia.
3

Podczas projektowania dowolnej aplikacji należy oddzielić dane od logiki programu. Czy związki chemiczne rzeczywiście są częścią logiki programu, a nie danych, na których działa logika programu?

Gdy są to dane, znacznie lepiej byłoby nie traktować ich jako wyliczeń, ale raczej czytać ich nazwy i właściwości z pliku konfiguracyjnego i przechowywać je w strukturze danych. Ułatwiłoby to również konserwację. Kiedy trzeba dodać nowe związki lub znaleźć błąd we właściwościach jednego, można po prostu edytować plik konfiguracyjny.

Philipp
źródło
1
+1 @ GlenH7 pomógłbyś wyjaśnić, dlaczego określone związki chemiczne są częścią kodu, szczególnie po tym, jak powiedziałeś, że „równanie jest takie samo dla wszystkich związków”.
Caleb,
1
@ GlenH7: Nadal nie ma powodu, dla którego chemikalia to nie tylko dane. Kilka plakatów pomaga ci nie używać wyliczenia. Na pewno nie.
kevin cline,
1
@kevincline & caleb (i właściwie wszyscy inni), stworzyłem meta pytanie z prośbą o pomoc w ustrukturyzowaniu tego pytania i jego enum. Byłbym wdzięczny za twoją opinię.
3
Cóż, kiedy ktoś przychodzi do ciebie z nożem utkwionym w głowie i prosi cię o spojrzenie na drzazgę w dłoni, ciężko się na tym skoncentrować.
Filipiny,
1
@Caleb - Pytanie zaktualizowane, aby lepiej wyjaśnić użycie wyliczenia.
3

Wydaje się, że można go lepiej zaimplementować jako klasę, która może rozszerzać i tłumaczyć w zależności od potrzeb programistów. Poniżej znajduje się próbka C #, którą wymyśliłem, aby umożliwić kilka dobrze zdefiniowanych zdefiniowanych chemikaliów (jako właściwości), a następnie zapytań do sklepów (za pośrednictwem Addi Getmetod). Możesz również dość łatwo rozszerzyć, aby mieć dostęp do swojej masy molowej i innych właściwości chemicznych.

public interface IChemical
{
    string AtomicFormula
    {
        get;
    }

    string ChemicalName
    {
        get;
    }

    string AbbreviatedChemicalName
    {
        get;
    }
}

public sealed class Chemical : IChemical
{
    private static readonly IChemical h2so4 = new Chemical("H2SO4", "sulfuric acid", "sulf. acid");

    private static readonly IChemical hcl = new Chemical("HCl", "hydrochloric acid", "hydro. acid");

    private static readonly IDictionary<string, IChemical> chemicalsByAtomicFormula = new Dictionary<string, IChemical>();

    private static readonly IDictionary<string, IChemical> chemicalsByChemicalName = new Dictionary<string, IChemical>();

    private static readonly IDictionary<string, IChemical> chemicalsByAbbreviatedChemicalName = new Dictionary<string, IChemical>();

    private readonly string atomicFormula;

    private readonly string chemicalName;

    private readonly string abbreviatedChemicalName;

    static Chemical()
    {
        chemicalsByAtomicFormula.Add(h2so4.AtomicFormula, h2so4);
        chemicalsByChemicalName.Add(h2so4.ChemicalName, h2so4);
        chemicalsByAbbreviatedChemicalName.Add(h2so4.AbbreviatedChemicalName, h2so4);
        chemicalsByAtomicFormula.Add(hcl.AtomicFormula, hcl);
        chemicalsByChemicalName.Add(hcl.ChemicalName, hcl);
        chemicalsByAbbreviatedChemicalName.Add(hcl.AbbreviatedChemicalName, hcl);
    }

    public Chemical(string atomicFormula, string chemicalName, string abbreviatedChemicalName)
    {
        if (string.IsNullOrWhiteSpace(atomicFormula))
        {
            throw new ArgumentException("Atomic formula may not be null or whitespace.", "atomicFormula");
        }

        if (string.IsNullOrWhiteSpace(chemicalName))
        {
            throw new ArgumentException("Chemical name may not be null or whitespace.", "chemicalName");
        }

        if (string.IsNullOrWhiteSpace(abbreviatedChemicalName))
        {
            throw new ArgumentException("Abbreviated chemical name may not be null or whitespace.", "abbreviatedChemicalName");
        }

        this.atomicFormula = atomicFormula;
        this.chemicalName = chemicalName;
        this.abbreviatedChemicalName = abbreviatedChemicalName;
    }

    public static IChemical H2SO4
    {
        get
        {
            return h2so4;
        }
    }

    public static IChemical HCl
    {
        get
        {
            return hcl;
        }
    }

    public string AtomicFormula
    {
        get
        {
            return this.atomicFormula;
        }
    }

    public string ChemicalName
    {
        get
        {
            return this.chemicalName;
        }
    }

    public string AbbreviatedChemicalName
    {
        get
        {
            return this.abbreviatedChemicalName;
        }
    }

    public static void AddChemical(IChemical chemical)
    {
        if (chemical == null)
        {
            throw new ArgumentNullException("chemical", "chemical may not be null");
        }

        if (chemicalsByAtomicFormula.ContainsKey(chemical.AtomicFormula))
        {
            return;
        }

        chemicalsByAtomicFormula.Add(chemical.AtomicFormula, chemical);

        if (chemicalsByChemicalName.ContainsKey(chemical.ChemicalName))
        {
            return;
        }

        chemicalsByChemicalName.Add(chemical.ChemicalName, chemical);

        if (chemicalsByAbbreviatedChemicalName.ContainsKey(chemical.AbbreviatedChemicalName))
        {
            return;
        }

        chemicalsByAbbreviatedChemicalName.Add(chemical.AbbreviatedChemicalName, chemical);
    }

    public static IChemical GetChemicalByAtomicFormula(string atomicFormula)
    {
        if (string.IsNullOrWhiteSpace(atomicFormula))
        {
            throw new ArgumentException("Atomic formula may not be null or whitespace.", "atomicFormula");
        }

        IChemical chemical;

        return chemicalsByAtomicFormula.TryGetValue(atomicFormula, out chemical) ? chemical : null;
    }

    public static IChemical GetChemicalByChemicalName(string chemicalName)
    {
        if (string.IsNullOrWhiteSpace(chemicalName))
        {
            throw new ArgumentException("Chemical name may not be null or whitespace.", "chemicalName");
        }

        IChemical chemical;

        return chemicalsByChemicalName.TryGetValue(chemicalName, out chemical) ? chemical : null;
    }

    public static IChemical GetChemicalByAbbreviatedChemicalName(string abbreviatedChemicalName)
    {
        if (string.IsNullOrWhiteSpace(abbreviatedChemicalName))
        {
            throw new ArgumentException("Abbreviated chemical name may not be null or whitespace.", "abbreviatedChemicalName");
        }

        IChemical chemical;

        return chemicalsByAbbreviatedChemicalName.TryGetValue(abbreviatedChemicalName, out chemical) ? chemical : null;
    }
}

możesz dodawać nowe chemikalia takie jak:

        Chemical.AddChemical(new Chemical("Na2SiF6", "sodium hexafluorosilicate", "sod. hex.flu.sil."));

i zdobądź inne bity jako takie:

        Console.WriteLine(Chemical.GetChemicalByChemicalName("sulfuric acid").AtomicFormula);
Jesse C. Slicer
źródło
Dziękuję za odpowiedź i zaktualizowałem moje pytanie, aby było bardziej jasne w tym, na co celuję. Nie martwię się tak bardzo o nazwę związku chemicznego, jak o dostęp do jego właściwości z różnych tabel i tym podobnych. Mam otwarte pytanie meta dotyczące tego, czy powinienem dodać do dyskusji enum, czy też podzielić ją na osobne