Creating objects and basic data input validation

Typically if you create an object and then use it’s methods you don’t want to pass parameters in several steps. Most parameters or better all of them should be passed to type constructor which then validates these parameters before you can use any method or property.

Typical class with private fields and a constructor looks like this:

    class EmailSender
    {

        private String Sender;
        private List Recepients;
        private String Body;

        public EmailSender(String Sender, List Recepients, String Body)
        {
            this.Recepients = Recepients;
            this.Sender = Sender;
            this.Body = Body;
        }
    }

You pass a number of parameters and their values (or references) are being linked with your private fields. Looks OK ? Wrong…

First off you should be checking all parameters if they meet requirements.

        private EmailSender(String Sender, List Recepients, String Body)
        {
             ValidateInputParameters(Sender, Recepients, Body);
            this.Recepients = Recepients;
            this.Sender = Sender;
            this.Body = Body;
        }

 

Something like this:

        private void ValidateInputParameters(String Sender, List Recepients, String Body)
        {
            try
            {
                if (String.IsNullOrEmpty(Sender)) throw new ArgumentNullException("Sender");
                ValidateRecepients(Recepients);
                if (String.IsNullOrEmpty(Body)) throw new ArgumentNullException("Body");
                ValidateEmail(Sender);
                if (Body.Length < MinimumBodyLength) throw new ArgumentException("Body can't be too small", nameof(Body));
            }
            catch (Exception ex)
            {
                Logging.ErrLog(ex, "Error validating input parameters ");
                throw;
            }
        }

This is just an example, this method checks each of parameters if it is not empty, not null also checks if emails are really emails. Looks fine. Almost. The problem with this approach is that it’s nice if you have one, two or three parameters. But what if you have this:

        public EmailSender(String Sender, List Recepients, String Body, String Host, String User, String Password, int Port, String CC, String BCC, String Subject, String SubjectCharset, String BodyCharset)
        {
            ValidateInputParameters(String Sender, List Recepients, String Body, String Host, String User, String Password, int Port, String CC, String BCC, String Subject, String SubjectCharset, String BodyCharset);
            this.Recepients = Recepients;
            this.Sender = Sender;
            this.Body = Body;
            this.Host = Host;
            this.Port = Port;
            //some more assignments
        }

and imagine this object is used in 500 places in your application. Would you like to correct all 500 places every time you need to change number of parameters ? General rule is that if you have more than three parameters then you should create a class or a struct to pass them. Sometimes such small classes are referred to as Data Transfer Objects (DTO):

    class EmailMessageDTO
    {
        public String Sender { get; set; }
        public String Recepients { get; set; }
        public String Body { get; set; }
    }
        public EmailSender(EmailMessageDTO Message)
        {
            ValidateInputParameters(Message);
            this.Recepients = Message.Recepients;
            this.Sender = Message.Sender;
            this.Body = Message.Body;
        }

        private void ValidateInputParameters(EmailMessageDTO Message )
        {
            try
            {

Look, we’ve got one parameter in both constructor and validate method. Makes it much easier to change number of parameters. You have no only two places to edit each time you change parameters, in constructor and in validation. And sometimes you can omit even that in constructor (provided you do not need to transform or parse your DTO parameter object). Like this:

        public EmailSender(EmailMessageDTO Message)
        {
            ValidateInputParameters(Message);
             this.Message = Message;
        }

OK, but this is too easy. Let’s say external world passes Recipients (email addresses) in a form of one string, where addresses are separated by comma. But your EmailSender needs Recipients in a form of a list. You don’t force consumers of your API (your class) to adapt to you. You adapt your class. It’s cheaper, especially if this is big system and all other classes expect that you accept recipients in a form of string:

        public EmailSender(EmailMessageDTO Message)
        {
            ValidateInputParameters(Message);
              this.Recepients = GetTransformedList( Message.Recepients);
            this.Sender = Message.Sender;
            this.Body = Message.Body;
        }

Sometimes if a process of creating object is time/resource consuming and prone to errors you may want to make it more safe and described in log file in more details. In such case you may hide constructor by making it private and exposing static public creation function:

                 
        public static EmailSender Create(EmailMessageDTO Message)
        {
            try
            {
                //some complicated process
                return new EmailSender(Message);
            }
            catch (Exception ex)
            {
                Logging.ErrLog(ex,"Error creating EmailSender object.");
                return null;
            }
        }
        private EmailSender(EmailMessageDTO Message)
        {
            ValidateInputParameters(Message);
            this.Recepients = GetTransformedList( Message.Recepients);
            this.Sender = Message.Sender;
            this.Body = Message.Body;
        }

Stay vigilant ! By returning null in case of creation failure you force your API (class) user to check if received data is null or not, otherwise they get Null Reference Exception. You may want to look at my other blog post about returning result together with object, and exceptions, to learn when to throw exception to executing method and when to return creation result with (or without) created object.

In some rare occasions it is even suggested to return an object in case of exception (failure), but not original (in this case EmailSender) object but rather special version of it (derived from it), that is empty, has no data, and it’s Send method does absolutely nothing (may write warning to log file). It depends on convention you accept in the beginning of a project. In case of string return value may be String.Empty, and in case of a list you can return for example new List<String>(). It is somewhat misleading, because you return values which are safe but empty only because process failed. It may be wise to return such empty, safe value but together with information that the process failed. So if the user (other developer) of your code forgets to check result then the application is not going to throw Null Reference Exception at him. An example of such dummy class:

    class EmailSenderNull: EmailSender
    {
        public EmailSenderNull()
        {
            //does nothing
        }

        public new bool Send() //we need to use 'new' keyword
        {
            //does nothing, always returns true
            Logging.Warning("An empty EmailSenderNull was created, Send does nothing");
            return true;
        }
    }

    class EmailSender
    {
        public static EmailSender Create(EmailMessageDTO Message)
        {
            try
            {
                return new EmailSender(Message);
            }
            catch (Exception ex)
            {
                Logging.ErrLog(ex, "Error creating EmaiLSender object");
                return new EmailSenderNull();
            }
        }

A lot of classes exist only for one reason. For example EmailSender exists only for the reason of sending emails and have only one public method exposed which is Send(). In such case the only one public Send method can be static:

        public static bool Send(EmailMessageDTO Message)
        {
            try
            {
                var sender = new EmailSender(Message);
                sender.Send();
                return true;
            }
            catch (Exception ex)
            {
                Logging.ErrLog(ex, "Error creating EmailSender object.");
                return false;
            }
        }

        private void Send()
        {
            //sending email, may throw exception
        }

We’ve got one internal private Send method that really sends email, but this API makes it much easier to send an email without need of separate creation of object and sending. Static Send method returns true or false as result, but may return complex type consisting of exceptions, data validation information, result in a form of enum {sentOK, failedPermanent, failedTemporary, badInput}  etc. Such approach hides all nuances of email creation and sending process from external users. They don’t need to know more if this is just a simple email sender.

One last tip for class fields that are initiated with constructor parameters is too make them readonly. They typically do not change in lifetime of your object. And they shouldn’t:

    class EmailSender
    {

        private readonly String Sender;
        private readonly List Recepients;
        private readonly String Body;

These vital fields can only be initiated once and cannot be changed anymore. This is your basic set of data that went thru validation in constructor.

Thanks for reading

Dominik Steinhauf

CEO, IT for 20 years, .Net developer, software architect at Creative Yellow Solutions (formerly Indesys)

If you need help with your software project, or need customized software for your company, contact me at:
dominik.steinhauf ( at) cys.biz.pl

Leave a Reply

Your email address will not be published. Required fields are marked *