Class Diagrams

The Create methods support creating mermaid class diagrams

Manual

There is a programmatic API that allows for custom class diagrams from code


var result = ClassDiagramBuilder.Create(
    [
        new ClassModel(
            "Animal",
            Members:
            [
                new MemberModel("age", MemberVisibility.Public, TypeName: "int"),
                new MemberModel("gender", MemberVisibility.Public, TypeName: "String"),
                new MemberModel("isMammal", MemberVisibility.Public, Parameters: []),
                new MemberModel("mate", MemberVisibility.Public, Parameters: []),
            ],
            Notes: "can fly\ncan swim\ncan dive\ncan help in debugging"
        ),
        new ClassModel(
            "Duck",
            Members:
            [
                new MemberModel("beakColor", MemberVisibility.Public, TypeName: "String"),
                new MemberModel("swim", MemberVisibility.Public, Parameters: []),
                new MemberModel("quack", MemberVisibility.Public, Parameters: []),
            ]
        ),
        new ClassModel(
            "Fish",
            Members:
            [
                new MemberModel("sizeInFeet", MemberVisibility.Private, TypeName: "int"),
                new MemberModel("canEat", MemberVisibility.Public, Parameters: []),
            ]
        ),
        new ClassModel(
            "Zebra",
            Members:
            [
                new MemberModel("is_wild", MemberVisibility.Public, TypeName: "bool"),
                new MemberModel("run", MemberVisibility.Public, Parameters: []),
            ]
        ),
    ],
    [
        new RelationshipModel("Duck", "Animal", RelationshipType.Inheritence),
        new RelationshipModel("Fish", "Animal", RelationshipType.Inheritence),
        new RelationshipModel("Zebra", "Animal", RelationshipType.Inheritence),
    ]
);

result.SaveResults();

classDiagram
`Animal` <|-- `Duck`
`Animal` <|-- `Fish`
`Animal` <|-- `Zebra`
note for `Animal` "can fly
can swim
can dive
can help in debugging"
class `Animal`
`Animal` : +int age
`Animal` : +String gender
`Animal` : +isMammal() 
`Animal` : +mate() 
class `Duck`
`Duck` : +String beakColor
`Duck` : +swim() 
`Duck` : +quack() 
class `Fish`
`Fish` : -int sizeInFeet
`Fish` : +canEat() 
class `Zebra`
`Zebra` : +bool is_wild
`Zebra` : +run() 

From Types

Given a set of Types it can generate a class diagram and automatic relationships,


interface ILifeform
{
    void Breethe();
}

interface IAnimal : ILifeform
{
    void Eat();

    string Call();
}

abstract class Bird : IAnimal
{
    public void Eat() => throw new NotSupportedException();

    public abstract string Call();

    public void Breethe() => throw new NotSupportedException();
}

class Duck : Bird
{
    public override string Call() => "Quack Quack";
}

class Swan : Bird
{
    public override string Call() => "Honk Honk";
}

class Dog : IAnimal
{
    public void Eat() => throw new NotSupportedException();

    public string Call() => "Woof Woof";

    public void Breethe() => throw new NotSupportedException();
}

[Fact(DisplayName = "Create a ClassDiagram with inheritance")]
public static async Task Case6()
{
    var result = ClassDiagramBuilder.Create(
        [
            typeof(ILifeform),
            typeof(IAnimal),
            typeof(Bird),
            typeof(Swan),
            typeof(Duck),
            typeof(Dog),
        ]
    );
    result.SaveResults();

    await Verify(result).UseDirectory("__snapshots__");
}

classDiagram
`ClassDiagramTests.IAnimal` <|-- `ClassDiagramTests.Bird`
`ClassDiagramTests.IAnimal` <|-- `ClassDiagramTests.Dog`
`ClassDiagramTests.Bird` <|-- `ClassDiagramTests.Duck`
`ClassDiagramTests.ILifeform` <|-- `ClassDiagramTests.IAnimal`
`ClassDiagramTests.Bird` <|-- `ClassDiagramTests.Swan`
class `ClassDiagramTests.Bird`
<<abstract>> `ClassDiagramTests.Bird`
`ClassDiagramTests.Bird` : +Breethe() void
`ClassDiagramTests.Bird` : +Call() string*
`ClassDiagramTests.Bird` : +Eat() void
`ClassDiagramTests.Bird` : +Equals(object obj) bool
`ClassDiagramTests.Bird` : -Finalize() void
`ClassDiagramTests.Bird` : +GetHashCode() int
`ClassDiagramTests.Bird` : +GetType() Type
`ClassDiagramTests.Bird` : -MemberwiseClone() object
`ClassDiagramTests.Bird` : +ToString() string
class `ClassDiagramTests.Dog`
`ClassDiagramTests.Dog` : +Breethe() void
`ClassDiagramTests.Dog` : +Call() string
`ClassDiagramTests.Dog` : +Eat() void
`ClassDiagramTests.Dog` : +Equals(object obj) bool
`ClassDiagramTests.Dog` : -Finalize() void
`ClassDiagramTests.Dog` : +GetHashCode() int
`ClassDiagramTests.Dog` : +GetType() Type
`ClassDiagramTests.Dog` : -MemberwiseClone() object
`ClassDiagramTests.Dog` : +ToString() string
class `ClassDiagramTests.Duck`
`ClassDiagramTests.Duck` : +Breethe() void
`ClassDiagramTests.Duck` : +Call() string
`ClassDiagramTests.Duck` : +Eat() void
`ClassDiagramTests.Duck` : +Equals(object obj) bool
`ClassDiagramTests.Duck` : -Finalize() void
`ClassDiagramTests.Duck` : +GetHashCode() int
`ClassDiagramTests.Duck` : +GetType() Type
`ClassDiagramTests.Duck` : -MemberwiseClone() object
`ClassDiagramTests.Duck` : +ToString() string
class `ClassDiagramTests.IAnimal`
<<interface>> `ClassDiagramTests.IAnimal`
`ClassDiagramTests.IAnimal` : +Call() string*
`ClassDiagramTests.IAnimal` : +Eat() void*
class `ClassDiagramTests.ILifeform`
<<interface>> `ClassDiagramTests.ILifeform`
`ClassDiagramTests.ILifeform` : +Breethe() void*
class `ClassDiagramTests.Swan`
`ClassDiagramTests.Swan` : +Breethe() void
`ClassDiagramTests.Swan` : +Call() string
`ClassDiagramTests.Swan` : +Eat() void
`ClassDiagramTests.Swan` : +Equals(object obj) bool
`ClassDiagramTests.Swan` : -Finalize() void
`ClassDiagramTests.Swan` : +GetHashCode() int
`ClassDiagramTests.Swan` : +GetType() Type
`ClassDiagramTests.Swan` : -MemberwiseClone() object
`ClassDiagramTests.Swan` : +ToString() string

From a single Type

Given a single Type it can build a full class diagram for that Type and all related Types


public class CustomList : List<int> { }

[Fact(DisplayName = "Create a ClassDiagram from a type exploded")]
public static async Task Case10()
{
    var result = ClassDiagramBuilder.Create(
        typeof(List<int>),
        assemblyTransformer: assemblies => assemblies.Append(typeof(ClassDiagramTests).Assembly)
    );

classDiagram
`List&ltint>` <|-- `ClassDiagramTests.CustomList`
`IEnumerable` <|-- `ICollection`
`IEnumerable` <|-- `ICollection&ltint>`
`IEnumerable&ltint>` <|-- `ICollection&ltint>`
`IEnumerable` <|-- `IEnumerable&ltint>`
`ICollection` <|-- `IList`
`IEnumerable` <|-- `IList`
`ICollection&ltint>` <|-- `IList&ltint>`
`IEnumerable` <|-- `IList&ltint>`
`IEnumerable&ltint>` <|-- `IList&ltint>`
`IEnumerable` <|-- `IReadOnlyCollection&ltint>`
`IEnumerable&ltint>` <|-- `IReadOnlyCollection&ltint>`
`IEnumerable` <|-- `IReadOnlyList&ltint>`
`IEnumerable&ltint>` <|-- `IReadOnlyList&ltint>`
`IReadOnlyCollection&ltint>` <|-- `IReadOnlyList&ltint>`
`IList` <|-- `List&ltint>`
`IList&ltint>` <|-- `List&ltint>`
`IReadOnlyList&ltint>` <|-- `List&ltint>`
`List&ltint>` "1"  <--  "1" `ClassDiagramTests.CustomList` : FindAll
`List&ltint>` "1"  <--  "1" `ClassDiagramTests.CustomList` : GetRange
`List&ltint>` "1"  <--  "1" `ClassDiagramTests.CustomList` : Slice
`List&ltint>` "1"  <--  "1" `List&ltint>` : FindAll
`List&ltint>` "1"  <--  "1" `List&ltint>` : GetRange
`List&ltint>` "1"  <--  "1" `List&ltint>` : Slice
class `ClassDiagramTests.CustomList`
`ClassDiagramTests.CustomList` : +int Capacity
`ClassDiagramTests.CustomList` : +int Count
`ClassDiagramTests.CustomList` : +int Item
`ClassDiagramTests.CustomList` : -int[] _items
`ClassDiagramTests.CustomList` : -int _size
`ClassDiagramTests.CustomList` : -int _version
`ClassDiagramTests.CustomList` : +Add(int item) void
`ClassDiagramTests.CustomList` : +AddRange(IEnumerable&ltint> collection) void
`ClassDiagramTests.CustomList` : +AsReadOnly() ReadOnlyCollection&ltint>
`ClassDiagramTests.CustomList` : +BinarySearch(int index, int count, int item, IComparer&ltint> comparer) int
`ClassDiagramTests.CustomList` : +BinarySearch(int item) int
`ClassDiagramTests.CustomList` : +BinarySearch(int item, IComparer&ltint> comparer) int
`ClassDiagramTests.CustomList` : +Clear() void
`ClassDiagramTests.CustomList` : +Contains(int item) bool
`ClassDiagramTests.CustomList` : +ConvertAll(Converter&ltint, TOutput> converter) List&ltTOutput>
`ClassDiagramTests.CustomList` : +CopyTo(int[] array) void
`ClassDiagramTests.CustomList` : +CopyTo(int index, int[] array, int arrayIndex, int count) void
`ClassDiagramTests.CustomList` : +CopyTo(int[] array, int arrayIndex) void
`ClassDiagramTests.CustomList` : +EnsureCapacity(int capacity) int
`ClassDiagramTests.CustomList` : +Equals(object obj) bool
`ClassDiagramTests.CustomList` : +Exists(Predicate&ltint> match) bool
`ClassDiagramTests.CustomList` : -Finalize() void
`ClassDiagramTests.CustomList` : +Find(Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +FindAll(Predicate&ltint> match) List&ltint>
`ClassDiagramTests.CustomList` : +FindIndex(Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +FindIndex(int startIndex, Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +FindIndex(int startIndex, int count, Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +FindLast(Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +FindLastIndex(Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +FindLastIndex(int startIndex, Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +FindLastIndex(int startIndex, int count, Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +ForEach(Action&ltint> action) void
`ClassDiagramTests.CustomList` : +GetEnumerator() List&ltint>.Enumerator
`ClassDiagramTests.CustomList` : +GetHashCode() int
`ClassDiagramTests.CustomList` : +GetRange(int index, int count) List&ltint>
`ClassDiagramTests.CustomList` : +GetType() Type
`ClassDiagramTests.CustomList` : -Grow(int capacity) void
`ClassDiagramTests.CustomList` : +IndexOf(int item) int
`ClassDiagramTests.CustomList` : +IndexOf(int item, int index) int
`ClassDiagramTests.CustomList` : +IndexOf(int item, int index, int count) int
`ClassDiagramTests.CustomList` : +Insert(int index, int item) void
`ClassDiagramTests.CustomList` : +InsertRange(int index, IEnumerable&ltint> collection) void
`ClassDiagramTests.CustomList` : +LastIndexOf(int item) int
`ClassDiagramTests.CustomList` : +LastIndexOf(int item, int index) int
`ClassDiagramTests.CustomList` : +LastIndexOf(int item, int index, int count) int
`ClassDiagramTests.CustomList` : -MemberwiseClone() object
`ClassDiagramTests.CustomList` : +Remove(int item) bool
`ClassDiagramTests.CustomList` : +RemoveAll(Predicate&ltint> match) int
`ClassDiagramTests.CustomList` : +RemoveAt(int index) void
`ClassDiagramTests.CustomList` : +RemoveRange(int index, int count) void
`ClassDiagramTests.CustomList` : +Reverse() void
`ClassDiagramTests.CustomList` : +Reverse(int index, int count) void
`ClassDiagramTests.CustomList` : +Slice(int start, int length) List&ltint>
`ClassDiagramTests.CustomList` : +Sort() void
`ClassDiagramTests.CustomList` : +Sort(IComparer&ltint> comparer) void
`ClassDiagramTests.CustomList` : +Sort(int index, int count, IComparer&ltint> comparer) void
`ClassDiagramTests.CustomList` : +Sort(Comparison&ltint> comparison) void
`ClassDiagramTests.CustomList` : -System.Collections.Generic.IEnumerable<T>.GetEnumerator() IEnumerator&ltint>
`ClassDiagramTests.CustomList` : -System.Collections.ICollection.CopyTo(Array array, int arrayIndex) void
`ClassDiagramTests.CustomList` : -System.Collections.IEnumerable.GetEnumerator() IEnumerator
`ClassDiagramTests.CustomList` : -System.Collections.IList.Add(object item) int
`ClassDiagramTests.CustomList` : -System.Collections.IList.Contains(object item) bool
`ClassDiagramTests.CustomList` : -System.Collections.IList.IndexOf(object item) int
`ClassDiagramTests.CustomList` : -System.Collections.IList.Insert(int index, object item) void
`ClassDiagramTests.CustomList` : -System.Collections.IList.Remove(object item) void
`ClassDiagramTests.CustomList` : +ToArray() int[]
`ClassDiagramTests.CustomList` : +ToString() string
`ClassDiagramTests.CustomList` : +TrimExcess() void
`ClassDiagramTests.CustomList` : +TrueForAll(Predicate&ltint> match) bool
class `ICollection`
<<interface>> `ICollection`
`ICollection` : +int Count
`ICollection` : +bool IsSynchronized
`ICollection` : +object SyncRoot
`ICollection` : +CopyTo(Array array, int index) void*
class `ICollection&ltint>`
<<interface>> `ICollection&ltint>`
`ICollection&ltint>` : +int Count
`ICollection&ltint>` : +bool IsReadOnly
`ICollection&ltint>` : +Add(int item) void*
`ICollection&ltint>` : +Clear() void*
`ICollection&ltint>` : +Contains(int item) bool*
`ICollection&ltint>` : +CopyTo(int[] array, int arrayIndex) void*
`ICollection&ltint>` : +Remove(int item) bool*
class `IEnumerable`
<<interface>> `IEnumerable`
`IEnumerable` : +GetEnumerator() IEnumerator*
class `IEnumerable&ltint>`
<<interface>> `IEnumerable&ltint>`
`IEnumerable&ltint>` : +GetEnumerator() IEnumerator&ltint>*
class `IList`
<<interface>> `IList`
`IList` : +bool IsFixedSize
`IList` : +bool IsReadOnly
`IList` : +object Item*
`IList` : +Add(object value) int*
`IList` : +Clear() void*
`IList` : +Contains(object value) bool*
`IList` : +IndexOf(object value) int*
`IList` : +Insert(int index, object value) void*
`IList` : +Remove(object value) void*
`IList` : +RemoveAt(int index) void*
class `IList&ltint>`
<<interface>> `IList&ltint>`
`IList&ltint>` : +int Item*
`IList&ltint>` : +IndexOf(int item) int*
`IList&ltint>` : +Insert(int index, int item) void*
`IList&ltint>` : +RemoveAt(int index) void*
class `IReadOnlyCollection&ltint>`
<<interface>> `IReadOnlyCollection&ltint>`
`IReadOnlyCollection&ltint>` : +int Count
class `IReadOnlyList&ltint>`
<<interface>> `IReadOnlyList&ltint>`
`IReadOnlyList&ltint>` : +int Item
class `List&ltint>`
`List&ltint>` : +int Capacity
`List&ltint>` : +int Count
`List&ltint>` : +int Item
`List&ltint>` : -bool System.Collections.Generic.ICollection<T>.IsReadOnly
`List&ltint>` : -bool System.Collections.ICollection.IsSynchronized
`List&ltint>` : -object System.Collections.ICollection.SyncRoot
`List&ltint>` : -bool System.Collections.IList.IsFixedSize
`List&ltint>` : -bool System.Collections.IList.IsReadOnly
`List&ltint>` : -object System.Collections.IList.Item
`List&ltint>` : -int[] s_emptyArray$
`List&ltint>` : -int[] _items
`List&ltint>` : -int _size
`List&ltint>` : -int _version
`List&ltint>` : +Add(int item) void
`List&ltint>` : +AddRange(IEnumerable&ltint> collection) void
`List&ltint>` : -AddWithResize(int item) void
`List&ltint>` : +AsReadOnly() ReadOnlyCollection&ltint>
`List&ltint>` : +BinarySearch(int index, int count, int item, IComparer&ltint> comparer) int
`List&ltint>` : +BinarySearch(int item) int
`List&ltint>` : +BinarySearch(int item, IComparer&ltint> comparer) int
`List&ltint>` : +Clear() void
`List&ltint>` : +Contains(int item) bool
`List&ltint>` : +ConvertAll(Converter&ltint, TOutput> converter) List&ltTOutput>
`List&ltint>` : +CopyTo(int[] array) void
`List&ltint>` : +CopyTo(int index, int[] array, int arrayIndex, int count) void
`List&ltint>` : +CopyTo(int[] array, int arrayIndex) void
`List&ltint>` : +EnsureCapacity(int capacity) int
`List&ltint>` : +Equals(object obj) bool
`List&ltint>` : +Exists(Predicate&ltint> match) bool
`List&ltint>` : -Finalize() void
`List&ltint>` : +Find(Predicate&ltint> match) int
`List&ltint>` : +FindAll(Predicate&ltint> match) List&ltint>
`List&ltint>` : +FindIndex(Predicate&ltint> match) int
`List&ltint>` : +FindIndex(int startIndex, Predicate&ltint> match) int
`List&ltint>` : +FindIndex(int startIndex, int count, Predicate&ltint> match) int
`List&ltint>` : +FindLast(Predicate&ltint> match) int
`List&ltint>` : +FindLastIndex(Predicate&ltint> match) int
`List&ltint>` : +FindLastIndex(int startIndex, Predicate&ltint> match) int
`List&ltint>` : +FindLastIndex(int startIndex, int count, Predicate&ltint> match) int
`List&ltint>` : +ForEach(Action&ltint> action) void
`List&ltint>` : +GetEnumerator() List&ltint>.Enumerator
`List&ltint>` : +GetHashCode() int
`List&ltint>` : +GetRange(int index, int count) List&ltint>
`List&ltint>` : +GetType() Type
`List&ltint>` : -Grow(int capacity) void
`List&ltint>` : +IndexOf(int item) int
`List&ltint>` : +IndexOf(int item, int index) int
`List&ltint>` : +IndexOf(int item, int index, int count) int
`List&ltint>` : +Insert(int index, int item) void
`List&ltint>` : +InsertRange(int index, IEnumerable&ltint> collection) void
`List&ltint>` : -IsCompatibleObject(object value) bool$
`List&ltint>` : +LastIndexOf(int item) int
`List&ltint>` : +LastIndexOf(int item, int index) int
`List&ltint>` : +LastIndexOf(int item, int index, int count) int
`List&ltint>` : -MemberwiseClone() object
`List&ltint>` : +Remove(int item) bool
`List&ltint>` : +RemoveAll(Predicate&ltint> match) int
`List&ltint>` : +RemoveAt(int index) void
`List&ltint>` : +RemoveRange(int index, int count) void
`List&ltint>` : +Reverse() void
`List&ltint>` : +Reverse(int index, int count) void
`List&ltint>` : +Slice(int start, int length) List&ltint>
`List&ltint>` : +Sort() void
`List&ltint>` : +Sort(IComparer&ltint> comparer) void
`List&ltint>` : +Sort(int index, int count, IComparer&ltint> comparer) void
`List&ltint>` : +Sort(Comparison&ltint> comparison) void
`List&ltint>` : -System.Collections.Generic.IEnumerable<T>.GetEnumerator() IEnumerator&ltint>
`List&ltint>` : -System.Collections.ICollection.CopyTo(Array array, int arrayIndex) void
`List&ltint>` : -System.Collections.IEnumerable.GetEnumerator() IEnumerator
`List&ltint>` : -System.Collections.IList.Add(object item) int
`List&ltint>` : -System.Collections.IList.Contains(object item) bool
`List&ltint>` : -System.Collections.IList.IndexOf(object item) int
`List&ltint>` : -System.Collections.IList.Insert(int index, object item) void
`List&ltint>` : -System.Collections.IList.Remove(object item) void
`List&ltint>` : +ToArray() int[]
`List&ltint>` : +ToString() string
`List&ltint>` : +TrimExcess() void
`List&ltint>` : +TrueForAll(Predicate&ltint> match) bool

From Assemblies

Given a set of Assemblies it can build a class diagram from all exposed types


var result = ClassDiagramBuilder.Create(
    [typeof(ClassDiagramBuilder).Assembly],
    type =>
        type.IsPublic
        && !type.Name.Contains("ClassDiagramBuilder")
        && !type.Name.Contains("ModelTransformer")
        && !type.Name.Contains("ResultExtensions"),
    // filter out all non-public members
    classModelTransformer: classes =>
        classes.Select(@class =>
            @class with
            {
                Members = @class.Members?.Where(member =>
                    member.Visibility is MemberVisibility.Public
                ),
            }
        )
);
result.SaveResults();

classDiagram
`MemberModel` "*"  <--  "1" `ClassModel` : Members
`MemberVisibility` "1"  <--  "1" `MemberModel` : Visibility
`ParameterModel` "*"  <--  "1" `MemberModel` : Parameters
`RelationshipType` "1"  <--  "1" `RelationshipModel` : Type
`ClassModifier` "1"  <..  "1" `ClassModel` : Modifier
`MemberModifier` "1"  <..  "1" `MemberModel` : Modifier
`CardinalityType` "1"  <..  "1" `RelationshipModel` : Cardinality
class `CardinalityType`
<<enumeration>> `CardinalityType`
`CardinalityType`: ManyToMany
`CardinalityType`: ManyToOne
`CardinalityType`: OneToMany
`CardinalityType`: OneToOne
class `ClassModel`
`ClassModel` : +IEnumerable&ltMemberModel> Members
`ClassModel` : +ClassModifier? Modifier
`ClassModel` : +string Name
`ClassModel` : +string Notes
`ClassModel` : +IEnumerable&ltstring> Values
`ClassModel` : +GetType() Type
class `ClassModifier`
<<enumeration>> `ClassModifier`
`ClassModifier`: Abstract
`ClassModifier`: Interface
`ClassModifier`: Struct
class `MemberModel`
`MemberModel` : +MemberModifier? Modifier
`MemberModel` : +string Name
`MemberModel` : +IEnumerable&ltParameterModel> Parameters
`MemberModel` : +string TypeName
`MemberModel` : +MemberVisibility Visibility
`MemberModel` : +GetType() Type
class `MemberModifier`
<<enumeration>> `MemberModifier`
`MemberModifier`: Abstract
`MemberModifier`: Static
class `MemberVisibility`
<<enumeration>> `MemberVisibility`
`MemberVisibility`: Internal
`MemberVisibility`: Private
`MemberVisibility`: Protected
`MemberVisibility`: Public
class `ParameterModel`
`ParameterModel` : +string Name
`ParameterModel` : +string TypeName
`ParameterModel` : +GetType() Type
class `RelationshipModel`
`RelationshipModel` : +CardinalityType? Cardinality
`RelationshipModel` : +string FromType
`RelationshipModel` : +string Label
`RelationshipModel` : +string ToType
`RelationshipModel` : +RelationshipType Type
`RelationshipModel` : +GetType() Type
class `RelationshipType`
<<enumeration>> `RelationshipType`
`RelationshipType`: Aggregation
`RelationshipType`: Association
`RelationshipType`: Composition
`RelationshipType`: Dependency
`RelationshipType`: Inheritence
`RelationshipType`: LinkDashed
`RelationshipType`: LinkSolid
`RelationshipType`: Realization