Link to home
Start Free TrialLog in
Avatar of deleyd
deleydFlag for United States of America

asked on

Design of class interaction

I'm contemplating the design of classes, playing with a simple hypothetical design, and wondering if there's some general principle of good design this violates, and if there's a better way.

Say I have a class of Messages. Each message is a string. The Messages class holds a list of all the message strings.

I want to send these messages to their destination. Say, write them to a file. So I have a MessageSender class which does the job.

User generated image

using System;
using System.Collections.Generic;
using System.IO;

namespace TestMessages
{
    class Program
    {
        static void Main(string[] args)
        {
            var messages = new Messages();
            var messageSender = new MessageSender();
            messageSender.SendMessages();
        }
    }

    public class Messages
    {
        public static List<string> myMessages;
        public Messages()
        {
            myMessages = new List<String>(new string[] { "one", "two", "three" });
        }
    }

    class MessageSender
    {
        public void SendMessages()
        {
            using (StreamWriter writer = new StreamWriter("myFile.txt"))
            {
                foreach (string s in Messages.myMessages)
                {
                    writer.WriteLine(s);
                }
            }
        }
    }

}

Open in new window

This all works. But I see problems.

First there's the obvious static List in the Messages class, which makes it global and easily accessible, and abusable.

And the Messages class is just data with no behavior.

Second, I see MessageSender reaching in to class Messages and extracting the data. This is the one I'm not sure if it violates encapsulation, or some other good design principle.

I can make the MyMessages list not static:

User generated image
using System;
using System.Collections.Generic;
using System.IO;

namespace TestMessages
{
    class Program
    {
        static void Main(string[] args)
        {
            var messages = new Messages();
            var messageSender = new MessageSender(messages);
            messageSender.SendMessages();
        }
    }

    public class Messages
    {
        public List<string> myMessages;
        public Messages()
        {
            myMessages = new List<String>(new string[] { "one", "two", "three" });
        }
    }

    class MessageSender
    {
        private Messages messages;

        public MessageSender(Messages messages)
        {
            this.messages = messages;
        }

        public void SendMessages()
        {
            using (StreamWriter writer = new StreamWriter("myFile.txt"))
            {
                foreach (string s in messages.myMessages)
                {
                    writer.WriteLine(s);
                }
            }
        }
    }

}

Open in new window

I'm feeling like maybe SendMessages() should take some messages as a parameter:

User generated image

using System;
using System.Collections.Generic;
using System.IO;

namespace TestMessages
{
    class Program
    {
        static void Main(string[] args)
        {
            var messages = new Messages();
            var messageSender = new MessageSender();
            messageSender.SendMessages(messages);
        }
    }

    public class Messages
    {
        public List<string> myMessages;
        public Messages()
        {
            myMessages = new List<String>(new string[] { "one", "two", "three" });
        }
    }

    class MessageSender
    {
        public void SendMessages(Messages messages)
        {
            using (StreamWriter writer = new StreamWriter("myFile.txt"))
            {
                foreach (string s in messages.myMessages)
                {
                    writer.WriteLine(s);
                }
            }
        }
    }

}

Open in new window

Or I could move SendMessages() into the Messages class:

User generated image
using System;
using System.Collections.Generic;
using System.IO;

namespace TestMessages
{
    class Program
    {
        static void Main(string[] args)
        {
            var messages = new Messages();
            messages.SendMessages();
        }
    }

    public class Messages
    {
        public List<string> myMessages;
        public Messages()
        {
            myMessages = new List<String>(new string[] { "one", "two", "three" });
        }

        public void SendMessages()
        {
            using (StreamWriter writer = new StreamWriter("myFile.txt"))
            {
                foreach (string s in myMessages)
                {
                    writer.WriteLine(s);
                }
            }
        }
    }

}

Open in new window

It kind of looks better; however, now i have a reference to an output file in my Messages class. I don't think Messages include an output file. Also, do messages really know how to send themselves to a file?

I can move the file reference to a parameter. But I still have my Messages class doing I/O to a file. Should a Messages class know about files and I/O?

User generated image
using System;
using System.Collections.Generic;
using System.IO;

namespace TestMessages
{
    class Program
    {
        static void Main(string[] args)
        {
            var messages = new Messages();
            messages.SendMessages("myFile.txt");
        }
    }

    public class Messages
    {
        public List<string> myMessages;
        public Messages()
        {
            myMessages = new List<String>(new string[] { "one", "two", "three" });
        }

        public void SendMessages(string filename)
        {
            using (StreamWriter writer = new StreamWriter(filename))
            {
                foreach (string s in myMessages)
                {
                    writer.WriteLine(s);
                }
            }
        }
    }

}

Open in new window


So I guess my questions are:
1. Should Messages know how to send themselves?
2. Is it improper for another class to reach into the Messages class, grab it's data, and do something with it's data? What principle does this violate?
ASKER CERTIFIED SOLUTION
Avatar of Nitin Sontakke
Nitin Sontakke
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial