Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Inclusion inheritance for element children #638

Open
jubr opened this issue Mar 25, 2024 · 3 comments
Open

[Feature Request] Inclusion inheritance for element children #638

jubr opened this issue Mar 25, 2024 · 3 comments
Assignees

Comments

@jubr
Copy link

jubr commented Mar 25, 2024

Hi @davydkov, fist of all: thanks for creating the versatile LikeC4 while keeping the number of keywords in the language to a minimum! ❤️

I'm working on a large model for a project & I find myself having introduced a group element that I use exclusively for - drumroll… - grouping within a softwaresystem. Take this minimal example with the problem description added inline:

specification {
  element group
  element softwaresystem
  element container
}
model {
  softwaresystem sys "System" {
    group gA "Group A" {
      container c1 "A1" {
        -> gB.c1
        -> gB.c2
      }
      container c2 "A2"
      container c3 "A3"
    }
    group gB "Group B" {
      container c1 "B1"
      container c2 "B2"
    }
  }
}
views {
  // Now that I encapsulate child elements in these groups, I find that I have to include them explicitly every time like so:
  view of sys {
    include *,
      sys.gA.*,
      sys.gB.*,
  }
  // And for deeper connectivity very specificly, as not to show elements that do not have a relationship:
  view of gA.c1 {
    include *,
      sys.gA.c1 with { color green },
      -> sys.gA.* ->,
      sys.gA.* ->,
      sys.gB,
      sys.gB.*,
  }
}

The extra include/exclude code I need to add in all the views is really adding up :'(

I think what could really help in this case was if it would be possible to cause the automatic inclusion of direct children of an element. Perhaps with a new keyword along the lines of:

element group {
  include children // children | never | always | default
  // or `behavior group`, or `children includeWithParent`, or whatever best fits the direction you have in mind for LikeC4
  style {
    shape rectangle
    color slate
  }
}

Which would cause its direct children to also be included if this group element is included in a view.

Or perhaps this should even be encoded in the shape, since it it does not behave like a regular element:

element group {
  style {
    shape group // this could then also cause rendering with a dashed line and a transparent background…
    color slate
  }
}

What do you think?

PS. In absence of GitHub markdown recognizing LikeC4, I find using ```zig code blocks to do at least something for readability 😀

@davydkov
Copy link
Member

davydkov commented Mar 26, 2024

Hey @jubr,

Thank you for your interest in the project and for sharing your thoughts.
Your idea is really interesting and it provided me a fresh perspective.

I had a similar concept in mind - a "logical-only" element that exists in the model but is not displayed on diagrams, smth like a boundary/domain/zone. But later, I realized that presenting these elements on higher levels could be also beneficial.

Your idea takes it a step further by proposing the automatic inclusion of nested elements.
And I like it!

However, I believe this should be more closely tied to the view/predicate rather than being globally defined by the specification (specs modifications impact a lot and lead to unexpected results and diagram changes).

Here are my pennies

Predicate expressions sugar

Come up with a beautiful shortcut for:

include sys.ga, sys.ga.*

I'm open to suggestions.
Any ideas?

Expand rule

Something like:

expand sys.ga
expand element.type=group

Implicitly adds sys.ga.* to predicates with sys.ga

Any thoughts on this?


Have you seen this discussion #533?
@viktorgusev1984 suggested the bright idea of including views into views

PS Wow, thank you so much for the hint with zig

🤘

@jubr
Copy link
Author

jubr commented Mar 29, 2024

Tag-based inclusion with include element.tag=#dc1 seems like a very powerful idea, without introducing new language elements: 👍 Like!

I can understand that spec changes can have far-reaching consequences, but if one adheres to the Open-Closed Principle by providing new opt-in functionality this should not be a problem. Existing behavior can always be safeguarded with proper .spec.ts unit tests.

Since posting the feature request I'm now leaning towards breaking this up into 2 features, that together can provide the "group" behavior:

  1. elements can be auto-expanded in views, but keep treating them as a first-class element
    • the goal here is DRY: less repetition in views, for which model- and spec-level work best
    • specified at view, model, or spec level so it kind of behaves like style (see below)
    • three types of expand: none (default), all or withRelationships (so do not display unconnected elements)
  2. elements can be drawn like a group

This also means it can be worked on, delivered and applied to elements separately.
So, focusing on 1. this could be condensed into:

specification {
  element system { }
  element container { }
  element group {
    //expand none             // is the default, same as not specifying it
    //expand all              // these elements are auto-expanded (child elements included together with their parents)
    expand withRelationships  // child elements included, but only if they have in- or outgoing relationships to currently visible elements
  }
}
model {
  system sys {
    group ga {
      //expand withRelationships  // can also specify here, but DRY at spec level
      //expand none               // possibly negate all/withRelationships at spec level
      container c1 { }
    }
  }
}
views {
  view of sys {
    include *
    //expand sys.ga withRelationships  // addressing by FQN
    //expand element.type=group all    // addressing by element type
    //expand element.tag=#abc none     // addressing by tag
  }
}

What do you think, are we getting somewhere? 😛

@davydkov
Copy link
Member

Hey @jubr

My apologies for the delayed response; time seems to have slipped away.
After some experiments, I came to the conclusion that the "auto-expanding" behavior defined in the model often leads to unexpected results, particularly when such elements are deeply nested.

I have introduced expand predicate in v1.0.0, and results are much more prominent. I am pretty optimistic that this new predicate may be the most useful one.

I'm eager to hear your thoughts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants