wtorek, 5 listopada 2019

SOLID - S jak Single responsibility principle

Tym postem chciałbym rozpocząć, krótką powtórkę dobrych praktyk programistycznych. SOLID z pewnością można uznać za jedną z nich - każdy chce być SOLIDny :). Ten post będzie poświęcony pierwszej literze - S.

Single responsibility principle - klasa, funkcja czy moduł powinny mieć tylko jeden powód zmiany. Stosując tę zasadę w praktyce tworzymy kod, który jest:

  • prosty do zrozumienia
  • łatwy do debugowania
  • łatwy do zmiany - zmieniając pojedyncze zachowanie nie wpływamy na inne
  • łatwy do testowania - np. za pomocą unit testów
  • kod jest re-używalny - proste funkcje / klasy / moduły łatwo wdrożyć w nowych projektach
  • można podciągnąć pod to zasadę: lepiej robić jedną rzecz a dobrze niż 10 źle :)

Jak rozpoznać ów powód do zmiany? Jednym aspektem będzie tu pewna praktyka, drugim pomocnikiem będzie zadawanie sobie pytania "Co ta klasa / funkcja / moduł właściwie robi?". Jeżeli znajdziemy kilka odpowiedzi na to pytanie - łamiemy zasadę pojedynczej odpowiedzialności.

Zobaczmy na poniższy przykład:

    public class Report
    {
        private readonly string _connectionString;

        public Report(string connectionString)
        {
            _connectionString = connectionString;
        }

        public void CreateReport(int startId, string reportPath)
        {
            using var sqlConnection = new SqlConnection(_connectionString);
            sqlConnection.Open();
            var sqlCommand = sqlConnection.CreateCommand();
            sqlCommand.CommandText = "SELECT firstName, lastName, city, postalCode FROM person WHERE id > 200;";
            using var dataReader = sqlCommand.ExecuteReader();
            var personList = new List<Person>();
            while (dataReader.NextResult())
            {
                var person = new Person
                {
                    LastName = (string) dataReader["lastName"],
                    FirstName = (string) dataReader["firstName"],
                    City = (string) dataReader["city"],
                    PostalCode = (string) dataReader["postalCode"]
                };
                personList.Add(person);
            }

            var report = new StringBuilder();
            var xmlSerializer = new XmlSerializer(typeof(List<Person>));
            using var stringWriter = new StringWriter();
            xmlSerializer.Serialize(stringWriter, report);
            File.WriteAllText(reportPath, stringWriter.ToString());
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string City { get; set; }
        public string PostalCode { get; set; }
    }


Odpowiedzialnością metody CreateReport jest:

  • pobranie danych z bazy
  • stworzenie z danych XMLa (serializacja do XML)
  • zapis danych do pliku
Jak widać mamy tutaj jak na tacy podane 3 powody do zmiany tej metody:
  • źródło danych może zostać zmienione - zamiast bazy może to być plik, inny serwis itp
  • format danych które zapisujemy - obecnie jest to XML, w przyszłości być może JSON lub CSV
  • Raport zapisywany jest do pliku na dysku twardym, być może przyjdzie potrzeba zapisu danych do S3 na AWS
Powyższą metodę, a właściwie klasę wypadałoby podzielić na 3 mniejsze, dzięki czemu kod będzie prostszy w każdej z nich, testowalny, a w przypadku jego zmiany będzie to znacznie prostsze.

Brak komentarzy:

Prześlij komentarz