How to build a class structure, when members are also structured hierarchically?
Asked Answered
C

1

16

I'm building a PHP web application, that should provide to the user a possiblity to order an "installation"/setup of a (ConnectDirect or File Transfer Gateway) connection between him and another person/organization.

(The technical specifica of the connection implementation are not important -- in the application it's only about the connections as product, that can be ordered and managed.)

The classes hierarchy for its model layer should represent following real-world infrastructure:

  • There are connections, that can be ordered.
  • A connection can be an IBM Connect:Direct connnection or an IBM File Transfer Gateway connection.
  • A CD connection is direct from A (source) to B (target).
  • A FTGW connection consists physically of two connections: A (source) to the FTGW server and from the FTGW server to B (target) -- but logically (for the ordering user) it's also one connection.
  • (There is additionally a case of an FTGW connection, that uses Connect:Direct as protokoll.)
  • Every endpoint is either a source or a target.

So I see following logical elements: logical connection, physical connection, role (source and target), connection type, order, endpoint, endpoint type (CD and FTGW).

The structure I currently have looks like this:

connections&endpoints pseudo UML class diagramm

But there are some issues with it:

  1. There are two hierarchy trees, where each element of the one consists contains elements of a particular subset of the other (each CD connection consists of CD endpoints; each FTGW connection consists of two FTGW endpoints, or more correctly: each FTGW logical connection consists of two physical FTGW connections -- and each of them consists of an FTGW endpoint and the FTGW server as second endpoint).

    An alternative might be to replace the relationship betweet Endpoint and PsysicalConnection by two relationships: EndpointCD-PsysicalConnectionCD and EndpointFTGW-PsysicalConnectionFTGW.

replaced relationships

Pro: More consistent; eliminates the logical imprecision (or maybe even mistake) of the faked possibility to build every connection (type) from a pair of any endpoints. Contra: Actually the requirement to contain two endpoints is a characteristic of every psysical connection -- from this point of view the right place for this is the very basic PsysicalConnection class.

  1. Every endpoint can be both source and target and contains not only the common endpoint properties, but also source and target properties. That means, dependent on the currnt role of the endpoint some properties are waste. And this will also be influence the database structure (columns, that sometimes have to be set and sometimes have to bi NULL).

    An alternative is to extend the hierarchy...

    a. ...by classes like EndpointSource and EndpoitTarget inheriting directly from the Endpoint and being inherited by the classes EndpointCD and EndpointFTGW (that means: two identical subtrees -- under EndpointSource and under EndpointTarget);

    b. ...by classes like EndpointCDSource and EndpointCDTarget (inheriting from the class EndpointCD) and EndpointFTGWSource and EndpointFTGWTarget (inheriting from the class EndpointFTGW) being inherited each by the concrete CD or FTGW endpoint classes (that means: twice two identical subtrees);

    c. ...by classes like MyConcreteEndpoint***Source and MyConcreteEndpoint***Target inheriting from the concrete endpoint classes (that means: every MyConcreteEndpoint class becomes abstract and gets two sublesses -- MyConcreteEndpoint***Source and MyConcreteEndpoint***Target, e.g. EndpointCDLinux is now abstract and is inherited by EndpointCDLinuxSource and EndpointCDLinuxTarget).

    Pro: eliminates the waste properties. Contra: A (more) complex class hierarchy.

Well, it's about software architecture and should (and of course will) be my design decision. But it would be nice to hear/read some expert (or non-expert) thougts, how to handle such a case. What are proper ways to organize the logical items for an infrastructure like what I described?

Chaparral answered 15/2, 2016 at 17:20 Comment(5)
The bounty suggests you're looking for an answer drawing from credible and/or official sources, however that may be difficult to achieve without some degree of opinion or bias. Also, this is a very long description of a system design/architecture, I'm wondering if you'd have better luck if you broke it down into more easily digested separate questions which may be better for this Q&A format.Podiatry
@Podiatry Thank yoy for your comment. Yes, the bounty suggestion "answer from credible and/or official sources" actually might be a bit confucing here. I simply didn't find any better / more suitable option. About breaking the question down into less questions: Sure, I usually try to ask questions in way (following something like "single responsibility principle"). But in this case I have no idea, how to shorten the question -- it's long, but all its content is its description and some thougts to the problem.Chaparral
Did you try to start modelling from the other end? I see only data here. What is it for? Where is a behaviour, use-cases? Or do you simply need straight mapping from data to some objects (which is quite useless)?Looming
Woah. I know how I'd do it - but even with ten years experience as a middleware solution architect, I would not call my modelling of these objects anything but personal preference. And frankly, I'd shy away from modelling such complicated structures in PHP. Although I might make sure that my PHP objects reflect a structure designed in some back end application.Wellread
What I see is in my opinion what you are trying to model hardware specifics too close to such thing as class hierarchy. Maybe you should try to abstract your class hierarchy from actual concreate specifics of particular domain logic. Final strcuture will of course contains similar concrete classes as you defined. but istead of building 2+ parallel hierarchies it is simplied to use such thing as interfaces, builders and factories to manage, build and validate possible configurations, while hierarchy is not bound to domain logics "with nails".Deangelis
D
1

Maybe I am overthinking, but I suggest for you to use slightly different model to reflect your business logic.

Following could be a total misunderstanding, but I'll give it a shot.

So:

Basing on what in fact any connection is, here is a concept:

  • Every connection is a collection of Nodes through which data should travel in order to reach its destination.
  • Each node can connect with next node using specific protocol, which is specific only to direct connection between two particular nodes.
  • Protocol has its own properties common for source and target nodes

Basing on this I suggest following model of building, managing and storing a configuration of Product:

enter image description here

Here:

  • LogicalConnection is reference to built composition of actual Connection, Node and Protocol classes

  • Connection contains a double-linked list of Nodes which are composed in order as data flows. i.e.: 1st element is source node and 2nd is its target and so on.

  • Concrete Node contains platform specific configuration, reference to target (*Node), source node (*Node) and concrete protocol (*Protocol)

  • Protocol contains its specific configuration for source and target, Node instances may refer to Protocol instance to extract required configuration.

  • Target and Source Nodes "see" each-other and source-target protocol configuration via double-linked list structure.

  • Configurations\*ConfigBuilder implementations orchestrate process of accepting data from UI and transforming it into actual composition of Connection, Node and Protocol depending on case.

  • IBM\ConnectDirect\ and IBM\FTGW\ namespaces contain concrete realizations for Protocol and *Node (e.g. WindowsNode, UnixNode)

If there still is a need for Node or Protocol to contain both source and target related attributes and part of them still could be NULL in some configurations - I suggest to use EAV storage model for DB if there is any concern about unused columns etc..

Using suggested model connections you described in question could be represented as following:

Connection:IBM_CD {
  nodes:[
    {//LinuxNode
      target:*nextElement,
      protocol:{//IBM.ConnectDirect.Protocol
        ..target attributes..
        ..source attributes..
      }
      ..platform specific attributes..
    },
    {//WindowsShareNode
      target:*nil,
      protocol:{
        //IBM.ConnectDirect.Protocol(same instance or null)
      }
      ..platform specific attributes..
    },
  ]
}

Connection:IBM_FTGW {
  nodes:[
    {//LinuxNode
      target:*nextElement,
      source:*nil,
      protocol:{//IBM.FTGW.Protocol
        ..target attributes..
        ..source attributes..
      }
      ..platform specific attributes..
    },
    {//IntermediateServerLinuxNode
      target:*nextElement,
      source:*prevElement,
      protocol:{//IBM.FTGW.Protocol
        ..target attributes..
        ..source attributes..
      },
      ..platform specific attributes
    },
    {//WindowsShareNode
      target:*nil,
      source:*prevElement,
      protocol:*nil,
      ..platform specific attributes..
    }
  ]
} 
Deangelis answered 19/4, 2016 at 1:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.