<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Designproblem]]></title><description><![CDATA[<p>Hey,</p>
<p>mich beschäftigt seit einigen Tagen ein Designproblem.</p>
<p>Vereinfacht sieht es so aus, das ich eine Klasse Socket habe:</p>
<pre><code class="language-cpp">class Socket
{
protected:
 int sock;
 SocketAddr addr; // Klasse SocketAddr enthält sockaddr_in

public:
 Socket();
 ~Socket();

 void close();

 int&amp; getRawSocket() { return sock; }
};
</code></pre>
<p>Alles natürlich kein Problem.</p>
<p>Damit ich jedoch Verbindungen annehmen kann, brauche ich noch eine Klasse Listener. Die Verbindung wird duch ein Objekt der Klasse Client dargestellt. Dort werden später noch weitere Informationen zu der Verbindung gespeichert (Verbindungsdauer, Loginstatus, etc.).</p>
<p>Da habe ich dann auch zwei Möglichkeiten:<br />
Ich lasse Client und Listener von Socket erben. Aber kann man sagen &quot;Ein Client/Listener <strong>ist</strong> ein Socket&quot;?</p>
<p>Oder ich löse es über Komposition und sage: &quot;Ein Client/Listener <strong>hat</strong> ein Socket&quot;?</p>
<p>Das ist momentan die erste Frage, die mich quält... Ich kann mich nicht entscheiden, da sich beides für mich richtig anhört.</p>
<p>Doch das wirkliche Problem ist die Funktion accept der Klasse Listener. Ich muss nämlich auf sock und addr zugreifen, da diese verändert werden, wenn eine Verbindung angenommen wird.</p>
<p>Ich müsste sie also so realisieren, falls ich das über Komposition löse:</p>
<pre><code class="language-cpp">void Listener::accept(Socket&amp; newSock)
{
 newSock.getRawSocket() = accept(sock.getRawSocket(),(sockaddr_in *) &amp;newSock.getAddr(), &amp;newSock.getAddr().getLength());
}
</code></pre>
<p>Empfinde ich als sehr hässlich und der Client müsste auch eine Funktion getSock() zur Verfügung stellen, die ein Socket&amp; zurückgibt:</p>
<pre><code class="language-cpp">// ...
Client newClient;
listener.accept(newClient.getSocket());
</code></pre>
<p>Ich könnte auch einfach ein Client-Objekt vom Listener annehmen lassen, aber ich möchte flexibel bleiben.</p>
<p>Bei Vererbung fällt ein get-Aufruf raus, da ich auf die Member des Listener direkt zugreifen kann (protected):</p>
<pre><code class="language-cpp">void Listener::accept(Socket&amp; newSock)
{
 newSock.getRawSocket() = accept(sock,(sockaddr_in *) &amp;newSock.getAddr(), &amp;newSock.getAddr().getLength());
}
</code></pre>
<p>Alles in allem ist es aber nicht viel besser und noch immer unschön gelöst. Mich macht das schon so richtig traurig, dass ich da seit Tagen keine schönere Lösung finden kann. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Muss ich das tatsächlich so hinnehmen oder kann man das nicht besser machen? Ich möchte mich ja bei meinen OO Designs auch verbessern.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/266368/designproblem</link><generator>RSS for Node</generator><lastBuildDate>Thu, 03 Sep 2026 08:09:53 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/266368.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 07 May 2010 17:29:01 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Designproblem on Fri, 07 May 2010 17:29:01 GMT]]></title><description><![CDATA[<p>Hey,</p>
<p>mich beschäftigt seit einigen Tagen ein Designproblem.</p>
<p>Vereinfacht sieht es so aus, das ich eine Klasse Socket habe:</p>
<pre><code class="language-cpp">class Socket
{
protected:
 int sock;
 SocketAddr addr; // Klasse SocketAddr enthält sockaddr_in

public:
 Socket();
 ~Socket();

 void close();

 int&amp; getRawSocket() { return sock; }
};
</code></pre>
<p>Alles natürlich kein Problem.</p>
<p>Damit ich jedoch Verbindungen annehmen kann, brauche ich noch eine Klasse Listener. Die Verbindung wird duch ein Objekt der Klasse Client dargestellt. Dort werden später noch weitere Informationen zu der Verbindung gespeichert (Verbindungsdauer, Loginstatus, etc.).</p>
<p>Da habe ich dann auch zwei Möglichkeiten:<br />
Ich lasse Client und Listener von Socket erben. Aber kann man sagen &quot;Ein Client/Listener <strong>ist</strong> ein Socket&quot;?</p>
<p>Oder ich löse es über Komposition und sage: &quot;Ein Client/Listener <strong>hat</strong> ein Socket&quot;?</p>
<p>Das ist momentan die erste Frage, die mich quält... Ich kann mich nicht entscheiden, da sich beides für mich richtig anhört.</p>
<p>Doch das wirkliche Problem ist die Funktion accept der Klasse Listener. Ich muss nämlich auf sock und addr zugreifen, da diese verändert werden, wenn eine Verbindung angenommen wird.</p>
<p>Ich müsste sie also so realisieren, falls ich das über Komposition löse:</p>
<pre><code class="language-cpp">void Listener::accept(Socket&amp; newSock)
{
 newSock.getRawSocket() = accept(sock.getRawSocket(),(sockaddr_in *) &amp;newSock.getAddr(), &amp;newSock.getAddr().getLength());
}
</code></pre>
<p>Empfinde ich als sehr hässlich und der Client müsste auch eine Funktion getSock() zur Verfügung stellen, die ein Socket&amp; zurückgibt:</p>
<pre><code class="language-cpp">// ...
Client newClient;
listener.accept(newClient.getSocket());
</code></pre>
<p>Ich könnte auch einfach ein Client-Objekt vom Listener annehmen lassen, aber ich möchte flexibel bleiben.</p>
<p>Bei Vererbung fällt ein get-Aufruf raus, da ich auf die Member des Listener direkt zugreifen kann (protected):</p>
<pre><code class="language-cpp">void Listener::accept(Socket&amp; newSock)
{
 newSock.getRawSocket() = accept(sock,(sockaddr_in *) &amp;newSock.getAddr(), &amp;newSock.getAddr().getLength());
}
</code></pre>
<p>Alles in allem ist es aber nicht viel besser und noch immer unschön gelöst. Mich macht das schon so richtig traurig, dass ich da seit Tagen keine schönere Lösung finden kann. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Muss ich das tatsächlich so hinnehmen oder kann man das nicht besser machen? Ich möchte mich ja bei meinen OO Designs auch verbessern.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1893938</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1893938</guid><dc:creator><![CDATA[DesignFailed]]></dc:creator><pubDate>Fri, 07 May 2010 17:29:01 GMT</pubDate></item><item><title><![CDATA[Reply to Designproblem on Fri, 07 May 2010 17:39:00 GMT]]></title><description><![CDATA[<p>Ich würde Listener::accept() einen Socket-Pointer zurückgeben lassen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1893942</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1893942</guid><dc:creator><![CDATA[Janjan]]></dc:creator><pubDate>Fri, 07 May 2010 17:39:00 GMT</pubDate></item><item><title><![CDATA[Reply to Designproblem on Fri, 07 May 2010 18:01:55 GMT]]></title><description><![CDATA[<p>Janjan schrieb:</p>
<blockquote>
<p>Ich würde Listener::accept() einen Socket-Pointer zurückgeben lassen.</p>
</blockquote>
<p>In dem Fall müsste ich zwangsläufig mit new rummachen, was mir eigentlich auch misfällt. Da würde ich sogar den hässlichen Code bevorzugen, da so keine Speicherlöcher entstehen können.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1893950</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1893950</guid><dc:creator><![CDATA[DesignFailed]]></dc:creator><pubDate>Fri, 07 May 2010 18:01:55 GMT</pubDate></item><item><title><![CDATA[Reply to Designproblem on Fri, 07 May 2010 19:38:48 GMT]]></title><description><![CDATA[<p>Ich habe es so gelöst, dass meine Socket-Klasse ein möglichst einfacher Wrapper um <code>SOCKET</code> herum ist.</p>
<pre><code class="language-cpp">struct Socket : public noncopyable
	{
		typedef int Handle;

		Handle handle;
		bool isEvent;

		Socket();
		~Socket();

		bool isConnected() const;
		bool bind(uint port);

		bool connect(const char *host, unsigned short port);
		bool accept(Socket &amp;client, std::string *out_ipAddress = 0);
		void close();

		bool send(const void *data, size_t size);
		bool receive(void *out_data, size_t size, size_t &amp;out_received);
	};
</code></pre>
<p>Weiteres, wie Unterscheidung in Listener/Client, findet auf der nächsten Ebene statt, beispielsweise so:</p>
<pre><code class="language-cpp">struct Listener
{
	bool listen(unsigned short port);
	bool isClient() const;
	Client *accept();

private:

	Socket m_socket;
};

struct Client
{
	Socket socket; //für einfachen Zugriff (z. B. durch Listener)

	void close();
	bool send(..);
	bool receive(..);
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1893958</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1893958</guid><dc:creator><![CDATA[TyRoXx]]></dc:creator><pubDate>Fri, 07 May 2010 19:38:48 GMT</pubDate></item></channel></rss>