deleyd
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.
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:
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?
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?
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.
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);
}
}
}
}
}
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:
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);
}
}
}
}
}
I'm feeling like maybe SendMessages() should take some messages as a parameter: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);
}
}
}
}
}
Or I could move SendMessages() into the Messages class: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);
}
}
}
}
}
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?
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);
}
}
}
}
}
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.