Lessons learned oraz mieszanie logiki z danymi

Ten blog m.in. miał służyć wypisywaniu sytaucji, w których to czegoś się nauczyłem. Zazwyczaj jednak przeważa wstyd, że jeszcze do niedawna takie babole w kodzie waliłem 🙂 Ustaliłem nową kategorię – Lessons Learned. Jest to takie jakby wytłumaczenie, że już tak nie robię, ponieważ jestem świadom, że to złooooooo. Poniżej taki właśnie prosty przykład.

W kodzie poniższym, błędem jest mieszanie danych z logiką pobierania/zapisywania tych danych.

        [Serializable]
        public class UserSettings
        {
            private const string SettingsPath = "path.xml";

            public bool IsCustomFileUsed;
            public bool IsAccurateCalculationUsed;
            public string CalculationInputPath;
            // and so on ...

            public static UserSettings GetSettings()
            {
                var serializer = new XmlSerializer(typeof (UserSettings));
                using (var reader = new StreamReader(SettingsPath))
                {
                    return (UserSettings) serializer.Deserialize(reader);
                }
            }

            public static void SaveSettings(UserSettings settings)
            {
                var serializer = new XmlSerializer(typeof (UserSettings));
                using (var writer = new StreamWriter(SettingsPath))
                {
                    serializer.Serialize(writer, settings);
                }
            }
        }

Tutaj nawet nie chodzi o statyczne metody, które uniemożliwiają zrobienie z tym kodem cokolwiek innego. Lepiej podzielić, aby późniejsze konieczne zmiany w logice pobierania/zapisywania tych ustawień były robione w osobnym pliku. Analogicznie dodanie nowych ustawień nie będzie miało wpływu na logikę pobierania tych ustawień. Lepiej podgląda się zmiany w systemie kontroli wersji jak również (przede wszystkim) łatwiej zrozumieć ten kod.

Podpowiem jeszcze tylko, że wrzucanie regionów (#region) aby podzielić tę klasę funkcjonalnie jest lekarstwem gorszym od choroby.

Pierwsza wrzucona do kontroli wersji implementacja powinna bardziej przypominać dwa pliki poniżej.

Plik UserSettings:

        [Serializable]
        public class UserSettings
        {
            public bool IsCustomFileUsed;
            public bool IsAccurateCalculationUsed;
            public string CalculationInputPath;
            // and so on ...
        }

Plik UserSettingsRepository:

        public class UserSettingsRepository
        {
            private const string SettingsPath = "path.xml";

            public static UserSettings GetSettings()
            {
                var serializer = new XmlSerializer(typeof(UserSettings));
                using (var reader = new StreamReader(SettingsPath))
                {
                    return (UserSettings)serializer.Deserialize(reader);
                }
            }

            public static void SaveSettings(UserSettings settings)
            {
                var serializer = new XmlSerializer(typeof(UserSettings));
                using (var writer = new StreamWriter(SettingsPath))
                {
                    serializer.Serialize(writer, settings);
                }
            }
        }

Docelowo klasa UserSettingsRepository wygląda zupełnie inaczej, ponieważ wiele rzeczy doszło w trakcie życia projektu 🙂 A klasa UserSettings no cóż, też się zmieniała, ale poprzez dodawanie i zmianę nazw pól.

PS. mam przeczucie, że nazwa UserSettingsRepository jest chybiona, ale lepiej pisać posty takie niż żadne 😉

Advertisements
Ten wpis został opublikowany w kategorii Lessons Learned i oznaczony tagami . Dodaj zakładkę do bezpośredniego odnośnika.