Powiedzmy, że chciałbym napisać loggera. Wywołuję metodę i na moim historyListView
pojawia się odpowiedni napis w kolorze zależnym od podanej typu wiadomości. Najprościej można to zaimplementować tak:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Log(string message, LogType type = LogType.Info)
{
var timestamp = DateTime.Now.ToString("dd-MM-yyyy hh:mm:ss");
var msg = timestamp + " - " + message;
var color = Color.Black;
switch (type)
{
case LogType.Error:
color = Color.Red;
break;
case LogType.Warn:
color = Color.Orange;
break;
case LogType.Info:
color = Color.Black;
break;
}
ListViewItem item = new ListViewItem()
{
Text = msg,
ForeColor = color
};
historyListView.Items.Add(item);
historyListView.ScroolToEnd();
}
private void performActionButton_Click(object sender, EventArgs e)
{
Log("error", LogType.Error);
Log("warn", LogType.Warn);
Log("info", LogType.Info);
}
}
Tylko dlaczego Form
ma odpowiadać za logikę powstawania wiadomości? Wyodrębniłem to więc do osobnej klasy LogMessageCreator
:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Log(string message, LogType type = LogType.Info)
{
var logMessageCreator = new LogMessageCreator();
var item = logMessageCreator.Create(message, type);
historyListView.Items.Add(item);
historyListView.ScroolToEnd();
}
private void performActionButton_Click(object sender, EventArgs e)
{
Log("error", LogType.Error);
Log("warn", LogType.Warn);
Log("info", LogType.Info);
}
}
class LogMessageCreator
{
public ListViewItem Create(string message, LogType type = LogType.Info)
{
var timestamp = DateTime.Now.ToString("dd-MM-yyyy hh:mm:ss");
var msg = timestamp + " - " + message;
var color = Color.Black;
switch (type)
{
case LogType.Error:
color = Color.Red;
break;
case LogType.Warn:
color = Color.Orange;
break;
case LogType.Info:
color = Color.Black;
break;
}
ListViewItem item = new ListViewItem()
{
Text = msg,
ForeColor = color
};
return item;
}
}
Tylko znowu zakładając, że chciałbym w różnym miejscu inaczej wyświetlać wiadomości (raz np. z datą, a raz nie) to stworzyłem klasę, która odpowiada za skonfigurowanie sposobu wyświetlania wiadomości:
class LogMessageCreator
{
public ListViewItem Create(string message, LogType type, LogMessageCreatorOptions options = null)
{
if (options == null)
{
options = new LogMessageCreatorOptions();
}
var messageBuilder = new StringBuilder();
if (options.AddDateTime)
messageBuilder.Append(DateTime.Now.ToString("dd-MM-yyyy hh:mm:ss")).Append(" - ");
messageBuilder.Append(message);
var color = Color.Black;
switch (type)
{
case LogType.Error:
options.MessageColor = Color.Red;
break;
case LogType.Warn:
options.MessageColor = Color.Orange;
break;
case LogType.Info:
options.MessageColor = Color.Black;
break;
}
ListViewItem item = new ListViewItem()
{
Text = messageBuilder.ToString(),
ForeColor = options.MessageColor
};
return item;
}
}
class LogMessageCreatorOptions
{
public bool AddDateTime { get; set; } = true;
public Color MessageColor { get; set; } = Color.Black;
}
- Czy coś takiego jest ok? Czy powinienem iść dalej i jeszcze bardziej to komplikować? Pewnie coś by się znalazło.
- Czy ten zapis:
public bool AddDateTime { get; set; } = true;
public Color MessageColor { get; set; } = Color.Black;
jest ok? Czy może powinienem ustawić te właściwości w konstruktorze? A może dodać metodę CreateDefault
? Czy nie powinny one być czasem prywatne? Wydaje mi się, że nie muszą być prywatne, bo służą jako modele DTO
.
-
W ostatniej opcji do metody
Create
przesyłam obiektLogMessageCreatorOptions
, któremu potem wypełniam poleMessageColor
. Czy takie rozwiązanie jest ok? Wydaje mi się, że powinienem tylko odczytywać dane z tego obiektu, a nie wypełniać go jakimiś danymi. -
Czy czasem obiekt
LogMessageCreatorOptions
zamiast właściwościMessageColor
powinien posiadać właściwośćMessageType
? Wtedy nie musiałbym mu ustawiać właściwości o kolorze, a tylko odczytywałbym typ wiadomości i na podstawie tego tworzył zmienną z kolorem. Tylko czy takie rozwiązanie nie przeczy idei tego obiektu? On miał służyć temu w jaki sposób mają być wyświetlone te dane (ich formatowanie), a nie typ tych danych. A może kolor właśnie jest sposobem sformatowania danych? -
Mam wrażenie, że w programowaniu często problemy rozwiązuję "na czuja", tak jak mi się wydaję. Nie mam takiego określonego schematu - zadaniem tego obiektu jest XXX, więc nie może on robić YYY. Jak sobie z tym poradzić? Innym przykładem będzie to, że nie wiem, czy powinienem zrobić folder
Extensions
i tam umieszczać klasyStringExtensions
,DateTimeExtensions
.. czy może zrobić folderHelpers
i tam umieścić klasęExtensions
, w której miałbym wszystkie rozszerzenia..