Code review, wywoływanie serwisu WCF

UserServiceClient to WCF’owe proxy utworzone podczas Add Service Reference.
Następujący kawałek kodu:

    public class Service
    {
        public string GetUser(QueryCriterion queryCriterion)
        {
            using (var client = new UserServiceClient())
            {
                client.ClientCredentials.Windows.ClientCredential.Domain = "domain";
                client.ClientCredentials.Windows.ClientCredential.UserName = "user";
                client.ClientCredentials.Windows.ClientCredential.Password = "pass";

                var data = client.GetUser(queryCriterion);
               
                // more code
               
                return data;
            }
        }
        
        // more methods like GetUser(...)
    }

został zmieniony na poniższy:

    public class Service
    {
        public string GetUser(QueryCriterion queryCriterion)
        {
            using (var client = GetClient())
            {
                var data = client.GetUser(queryCriterion);
               
                // more code
               
                return data;
            }
        }

        private static UserServiceClient GetClient()
        {
            var userServiceClient = new UserServiceClient();

            userServiceClient.ClientCredentials.Windows.ClientCredential.Domain = "domain";
            userServiceClient.ClientCredentials.Windows.ClientCredential.UserName = "user";
            userServiceClient.ClientCredentials.Windows.ClientCredential.Password = "pass";

            return userServiceClient;
        }
        
        // more methods like GetUser(...)
    }

Prosty refactoring

Ideą była pozbycie się duplikacji czyli ustawiania w każdej metodzie domain/user/pass. Cel jak najbardziej szczytny, tylko że w tym przypadku ten kod może wykonać się inaczej po zmianie. W tym przypadku akurat nie spodziewamy się niczego niezwykłego. Załóżmy jednak, że ustwianie domeny rzuciło wyjątkiem. W drugim przypadku, mimo że stworzyliśmy obiekt UserServiceClient, to nie dotrwał on do końca metody GetClient(), czyli nie został przekazany do using’a wywołanie niżej, więc nie zostanie wywołane na nim Dispose().
Według mnie dyskwalifikuje to tego typu refactoring.

Sprzątanie

Nie wiem jakie byłoby prawidłowe rozwiązanie. Na szybko wymyśliłem coś takiego:

        private static UserServiceClient GetClient()
        {
            var client = new UserServiceClient();

            try
            {
                client.ClientCredentials.Windows.ClientCredential.Domain = "domain";
                client.ClientCredentials.Windows.ClientCredential.UserName = "user";
                client.ClientCredentials.Windows.ClientCredential.Password = "pass";
            }
            catch (Exception)
            {
                client.Dispose();

                throw;
            }

            return client;
        }

sprzatajaca miotla

Dzięki temu obiekt zostanie posprzątany, mimo że nie dotarł do docelowego using’a. Dobrze zaimplementowany interfejs IDisposable powinien zwolnić niezarządzane zasoby, gdy zdążyły już zostać utworzone lub nie zrobi nic, gdy jeszcze nie zostały utworzone. Oczywiście nie konsumujemy wyjątku, chcemy jedynie posprzątać.

A może macie jakieś lepsze pomysły?

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