Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. Project structure opinions?

Project structure opinions?

Scheduled Pinned Locked Moved The Lounge
discussionsysadmintutorialquestionworkspace
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Jon McKee
    wrote on last edited by
    #1

    For context, my current pet project is a modern implementation of the IRCv3 client protocol. It offers three layers to use depending on what you're looking for: directly to the IRC socket (raw messages), a broadcaster (contextual messages), or a "framework" of sorts that obscures details into easy-to-use interfaces like Server, LocalUser, Channel, etc. Anyway, I've realized my broadcaster folder is becoming irritating and slow to navigate. Between the "everything in one file"-type and the "one class per file"-type I very much lean towards the latter. However with roughly 200 distinct messages in the base protocol alone (not to mention CTCP, DCC, XDCC, SASL, etc) the one-class-per-file method is becoming ornery at best. After some thinking, I decided this would be a nice solution that would allow easy navigation since everything related to a message is contained in a single file:

    //Example RPL_WELCOME file
    public interface IWelcomeReply : IReply { }

    public partial class IrcBroadcaster
    {
    public event EventHandler WelcomeEvent;

    //Since partial constructors aren't allowed the "base" IrcBroadcaster will simply call
    //partial setup methods.
    private partial SetupWelcomeMessage()
    {
        \_commandMap.Add(
            MessageCommands.RPL\_WELCOME, 
            msg => WelcomeEvent?.Invoke(this, new Reply(msg))
        );
    }
    

    }

    //For many other messages, there are unique parameters so they'd have an interface implementation here.
    //IWelcomeReply is one of the simplest so that's not needed as Reply handles it.

    Before you'd have to sift through a minimum of 3 files among what would be over 600 to check/change something and the IrcBroadcaster class was a monster. This feels easier to navigate but I was wondering what your thoughts were? And if you've run into a similar situation what was your solution?

    F 1 Reply Last reply
    0
    • J Jon McKee

      For context, my current pet project is a modern implementation of the IRCv3 client protocol. It offers three layers to use depending on what you're looking for: directly to the IRC socket (raw messages), a broadcaster (contextual messages), or a "framework" of sorts that obscures details into easy-to-use interfaces like Server, LocalUser, Channel, etc. Anyway, I've realized my broadcaster folder is becoming irritating and slow to navigate. Between the "everything in one file"-type and the "one class per file"-type I very much lean towards the latter. However with roughly 200 distinct messages in the base protocol alone (not to mention CTCP, DCC, XDCC, SASL, etc) the one-class-per-file method is becoming ornery at best. After some thinking, I decided this would be a nice solution that would allow easy navigation since everything related to a message is contained in a single file:

      //Example RPL_WELCOME file
      public interface IWelcomeReply : IReply { }

      public partial class IrcBroadcaster
      {
      public event EventHandler WelcomeEvent;

      //Since partial constructors aren't allowed the "base" IrcBroadcaster will simply call
      //partial setup methods.
      private partial SetupWelcomeMessage()
      {
          \_commandMap.Add(
              MessageCommands.RPL\_WELCOME, 
              msg => WelcomeEvent?.Invoke(this, new Reply(msg))
          );
      }
      

      }

      //For many other messages, there are unique parameters so they'd have an interface implementation here.
      //IWelcomeReply is one of the simplest so that's not needed as Reply handles it.

      Before you'd have to sift through a minimum of 3 files among what would be over 600 to check/change something and the IrcBroadcaster class was a monster. This feels easier to navigate but I was wondering what your thoughts were? And if you've run into a similar situation what was your solution?

      F Offline
      F Offline
      Foothill
      wrote on last edited by
      #2

      Providing a simpler yet type safe way of handling messages from internet protocols is why I wrote the code in this article: C# Replacing switch(enum) flow control with Reflection[^]. Don't know if it will suit your goals but it worked for me while experimenting with client/server app development. Certain others didn't see the merit in it but everybody has their opinions.

      if (Object.DividedByZero == true) { Universe.Implode(); }

      J 1 Reply Last reply
      0
      • F Foothill

        Providing a simpler yet type safe way of handling messages from internet protocols is why I wrote the code in this article: C# Replacing switch(enum) flow control with Reflection[^]. Don't know if it will suit your goals but it worked for me while experimenting with client/server app development. Certain others didn't see the merit in it but everybody has their opinions.

        if (Object.DividedByZero == true) { Universe.Implode(); }

        J Offline
        J Offline
        Jon McKee
        wrote on last edited by
        #3

        For my code-base I'd been considering something like this to simplify the mapping code. I liked the article. It's a nice technique for niche situations like this. I'll be running the reflection in the static constructor instead of instance though since the mappings won't change during run-time.

        F 1 Reply Last reply
        0
        • J Jon McKee

          For my code-base I'd been considering something like this to simplify the mapping code. I liked the article. It's a nice technique for niche situations like this. I'll be running the reflection in the static constructor instead of instance though since the mappings won't change during run-time.

          F Offline
          F Offline
          Foothill
          wrote on last edited by
          #4

          Jon McKee wrote:

          I liked the article.

          Thanks.

          Jon McKee wrote:

          I'll be running the reflection in the static constructor instead

          That's how my original code was written. You can approach initializing your method maps in either way.

          if (Object.DividedByZero == true) { Universe.Implode(); }

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups