likec4 / likec4

Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code
https://likec4.dev
MIT License
307 stars 27 forks source link

[Feature Request] Allow for extending tags on elements #666

Open yoHasse opened 7 months ago

yoHasse commented 7 months ago

Hi! 👋

First off, thank you for this exceptional toolkit. It has significantly simplified visualizing my designs and is incredibly intuitive! 🙏

I'm working with a loosely coupled system spread across multiple directories (12+ and growing). It would be highly beneficial to have the ability to extend tags from one model to another without navigating the entire file structure.

I am not sure if this is the correct solution to the problem, but I can't think of anything else... 😥

Table of content:

Here's an example to illustrate the scenario:

Logical overview:

ExternalSourceA -> ServiceA -> MessageBroker.TopicA -> MessageBroker.SubscriptionA -> ServiceB
ExternalSourceA -> ServiceA -> MessageBroker.TopicA -> MessageBroker.SubscriptionB -> ServiceC

Current implementation sample:

/src/serviceA.c4

model {
    serviceA = context 'service A' {
        controller = container 'controller'
    }

    externalSystemA -> serviceA
    serviceA -> messageBroker.topic
    serviceA.controller -> messageBroker.topic
}

/src/serviceB.c4

model {
    serviceB = context 'service B' {
        subFetcher = container 'subFetcher'
    }

    messageBroker.subA -> serviceB.subFetcher

}

/src/serviceC.c4

model {
    serviceC = context 'service C' {
        subFetcher = container 'subFetcher'
    }

    messageBroker.subB -> serviceC.subFetcher
}

/src/externalSystemA.c4

model {
    externalSystemA = context 'externalSystemA'
}

/src/messageBroker.c4

model {
    messageBroker = context 'messageBroker' {
        topic = container 'topic'
        subA = container 'subscriptionA'
        subB = container 'subscriptionB'
    }

    messageBroker.topic -> subA
    messageBroker.topic -> subB
}

/src/views.c4

views {
    // Define views for system interaction
    view context-externalSystem2ServiceB of serviceB {
        include *, 
            serviceA, 
            externalSystemA, 
            serviceA.controller, 
            messageBroker, 
            messageBroker.topic, 
            messageBroker.subA,
    }

    view context-externalSystem2ServiceC of serviceC {
        include 
            serviceA, 
            externalSystemA, 
            serviceA.controller, 
            messageBroker, 
            messageBroker.topic, 
            messageBroker.subB,
    }
}

Example usage:

    extend serviceA {
        #externalSystem2ServiceB
    }

    extend messageBroker {
        #externalSystem2ServiceC
        subA {
            #externalSystem2ServiceB
        }
    }

After enhancement:

/src/serviceA.c4

model {
    serviceA = context 'service A' {
        controller = container 'controller'
    }

    externalSystemA -> serviceA
    serviceA -> messageBroker.topic
    serviceA.controller -> messageBroker.topic
}

/src/serviceB.c4

model {
    serviceB = context 'service B' {
        subFetcher = container 'subFetcher'
    }

    extend externalSystemA {
        #externalSystem2ServiceB
    }

    extend serviceA {
        #externalSystem2ServiceB
    }

    extend messageBroker {
        #externalSystem2ServiceB
        subA {
            #externalSystem2ServiceB
        }
    }

    messageBroker.subA -> serviceB.subFetcher

}

/src/serviceC.c4

model {
    serviceC = context 'service C' {
        subFetcher = container 'subFetcher'
    }

    extend externalSystemA {
        #externalSystem2ServiceC
    }

    extend serviceA {
        #externalSystem2ServiceC
    }

    extend messageBroker {
        #externalSystem2ServiceC
        subA {
            #externalSystem2ServiceC
        }
    }

    messageBroker.subB -> serviceC.subFetcher
}

/src/externalSystemA.c4
...

/src/messageBroker.c4
...

/src/views.c4

views {
    // Define views for system interaction
    view context-externalSystem2ServiceB of serviceB {
        include 
            *, 
            element.tag = #externalSystem2ServiceB

    }

    view context-externalSystem2ServiceC of serviceC {
        include 
            *,
            element.tag = #externalSystem2ServiceC
    }
}
ckeller42 commented 1 month ago

That would be a great feature that would help me. My use-case is that some of the model is auto-generated. But I would love to extend the generated parts with tags to allow e.g. color coding certain parts.