3. PlantUML Stdlib Under The Hood 2¶
3.1. Step-by-step Towards A Standard Macro¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | @startuml
'create equivalent of icons shown here https://github.com/awslabs/aws-icons-for-plantuml
sprite $Batch [64x64/16z] {
xLQ7bjim30CdzFzVtEV1iErPkJpT7iYm5aWDKERujFZ5Bp8YkSvM011VfMzSDy2Mw1JidbCGAtmllmbPuIkoImjyGUsyBV4LV95_Xny50bpW4uTRAjOKu81b
Xa0vbX3OKFG5C0IMNLyxXA_3PvW5hqHSOFBP_Ovk4036hYi0pJdTCgqD6A0g4FQ0hOwygxSikGOanw11AuvtomxXjNiRDECmn21xxTkJP0N4tdy1Gmu5T2GW
6ygFL_sqbx3NvA_FVtt_ri_F1CZNra-10TpNhvVr2KGcyVCOdoBySlpv-jC1ZSVveO36_Fwb0UASqGqG0QpfJgP2Eo60u59-fLVozhhdNk2WTeDpq2O6AAL_
uV7KGPNO2lya17gz1pMiD1VmFNH9IBLNe3xA3q07eNsMy_WdXESwU4jRmddEk-FUuPFjjthiqAEGVUz8rlqmsK1nhtYlklvp7vWRfka0jUNITUdTzgxFyzLx
-Ikh_YdmYr_y0G
}
rectangle "<color:red><$Batch></color>\n0" as rectangle
'Render a sprite
!procedure $ffoo1()
rectangle "<$Batch>\n1"
!endprocedure
$ffoo1()
'Render a sprite - with color red
!procedure $ffoo2()
rectangle "<color:red><$Batch></color>\n2" as 2
!endprocedure
$ffoo2()
'https://github.com/awslabs/aws-icons-for-plantuml/blob/master/dist/General/Disk.puml
'rectangle "==e_label\n<color:e_color><$e_sprite></color>\n//<size:TECHN_FONT_SIZE>[e_techn]</size>//" <<e_stereo>> as e_alias
'!define DiskParticipant(p_alias, p_label, p_techn, p_descr) AWSParticipant(p_alias, p_label, p_techn, p_descr, #232F3E, Disk, Disk)
'https://github.com/awslabs/aws-icons-for-plantuml/blob/master/source/AWSCommon.puml
'common.puml: rectangle "==e_label\n<color:e_color><$e_sprite></color>\n//<size:TECHN_FONT_SIZE>[e_techn]</size>//\n\n e_descr" <<e_stereo>> as e_alias
'Render a sprite - with color red - and add some text
!procedure $ffoo3()
rectangle "==label\n<color:red><$Batch></color>\n[technology]\n\n Description 3" as 3
!endprocedure
$ffoo3()
'Render a sprite - with color red - and add some text - with some formatting
!procedure $ffoo4()
rectangle "<<something>>\n==label\n<color:red><$Batch></color>\n//<size:12>[technology]</size>//\n\n Description 4" as 4
!endprocedure
$ffoo4()
'!procedure $ffoo5($alias, $description="", $label="", $technology="", $scale=1, $colour=red)
'OBSERVATION 1: the next line does not work - sprite is white - not red; there is where the unquoted keyword comes in
'rectangle "<<$alias>>\n==$label\n<color:$colour><$Batch*$scale></color>\n//<size:12>[$technology]</size>//\n\n $description 5" as 5
'the next line works i.e. sprite is red
'rectangle "<<//$alias//>>\n==$label\n"<color:red><$Batch*$scale></color>"\n//<size:12>[$technology]</size>//\n\n $description 5" as $alias
'!endprocedure
'$ffoo5("myalias", "mydescription", "mylabel", "mytechnology", 2, blue)
'unquoted means that you don't have to use quotes when calling the procedure
!unquoted procedure $ffoo51($alias, $description="", $label="", $technology="", $scale=1, $colour=red)
rectangle "<<$alias>>\n==$label\n<color:$colour><$Batch*$scale></color>\n//<size:12>[$technology]</size>//\n\n $description 51" as 5
!endprocedure
$ffoo51(myalias, mydescription, mylabel, mytechnology, 2, blue)
!procedure $ffoo6($alias, $description="", $label="", $technology="", $scale=1, $colour=red)
rectangle "<<//$alias//>>\n==$label\n<color:red><$Batch*$scale></color>\n//<size:12>[$technology]</size>//\n\n $description 6 " as $alias
!endprocedure
$ffoo6("myaliasbatch2", "mydescription", "mylabel", "mytechnology", 2, blue)
'OBSERVATION 2: can't do something like this
' $ffoo6($scale=2)
@enduml
|
3.2. Close But…¶
We can use the DefaultArgumentValue to avoid having to specify a parameter value when we call our procedure. BUT this only works if the default parameters are at the end i.e. it is all based on the order of the procedure parameters.
In other words, the user has to know/care about the order of parameters.
See Standard Library - What We Have And What We Want.
To specify color blue I need to do
`$ffoo6("myaliasbatch2", "mydescription", "mylabel", "mytechnology", 2, blue)`
What I want to do
`$ffoo6($color=blue)`
or
`$ffoo6($scale=2)`
3.3. Procedure Keyword Arguments¶
To enable the StdLib standardisation, I suggested the keyword arguments and Arnaud produced a release to play with next day - and this became part of an official release:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | @startuml
'all sprites in a category would be included in an all.puml file for that category
'==================================================================================================
'create equivalent of icons shown here https://github.com/awslabs/aws-icons-for-plantuml
sprite $Batch [64x64/16z] {
xLQ7bjim30CdzFzVtEV1iErPkJpT7iYm5aWDKERujFZ5Bp8YkSvM011VfMzSDy2Mw1JidbCGAtmllmbPuIkoImjyGUsyBV4LV95_Xny50bpW4uTRAjOKu81b
Xa0vbX3OKFG5C0IMNLyxXA_3PvW5hqHSOFBP_Ovk4036hYi0pJdTCgqD6A0g4FQ0hOwygxSikGOanw11AuvtomxXjNiRDECmn21xxTkJP0N4tdy1Gmu5T2GW
6ygFL_sqbx3NvA_FVtt_ri_F1CZNra-10TpNhvVr2KGcyVCOdoBySlpv-jC1ZSVveO36_Fwb0UASqGqG0QpfJgP2Eo60u59-fLVozhhdNk2WTeDpq2O6AAL_
uV7KGPNO2lya17gz1pMiD1VmFNH9IBLNe3xA3q07eNsMy_WdXESwU4jRmddEk-FUuPFjjthiqAEGVUz8rlqmsK1nhtYlklvp7vWRfka0jUNITUdTzgxFyzLx
-Ikh_YdmYr_y0G
}
'https://github.com/awslabs/aws-icons-for-plantuml/blob/master/dist/ARVR/ARVR.puml
sprite $Arvr [64x64/16z] {
xTG3WiH054NHzutP_th7RHkfsmnEdE1HZMZsIn0_DGDuuVsZJwnMVJ-57txuuKrsP4Tv1mjl3Nw43qZlo147VO9xPueyu8j1l3jm7V0GtPFWe8_UKzpL3rzc
TO4l0gZEzufCsDd-rnhoN2zKtKLoWk-bkHq--vabr0TypEy_WiwEmc9K7FATAd_fVDwOZygdU_uEF_pmLgUMA_wChkV1SavCc4LdXNVe2m
}
'https://github.com/awslabs/aws-icons-for-plantuml/blob/master/dist/ARVR/Sumerian.puml
sprite $Sumerian [64x64/16z] {
xPO5qkim38HN3FU_xuE29mMx-Hbtg4to6GIZxVVJhtvLLI-XbK2QJo6sVv90JA3SImUJRVuAjBeDl8zE0G2EyVy42d87NGOmGG0vVHuu7iRWZt4daBUWWW6j
8w_zNufuHES9KgxpKjr5o6CKQyh5uGi59BTfEuR1GHvEi6cu0N2sWE8sb99j03370L41CkryG9FQh6rTffOJlEWGLz-cbv5N4Pqh83Vf5THL67BA-qXltEu_
2XWrtrzlzZUfwuBCdjy_3ilGeY0Pgmj0NO5ehtb1vh9c0OhsaV_Qfa_hKUzKUDIs_eJgy7myMFEPLzinwd3nSQ0rpwYR_kiWmAgVmezmYuKSJ_94VZJDABad
y4EnAVcdyy4Xo6H_7g-02Se1oIVprMqKX_YdW9_AEtjtdVlNiykVmAS0Tjd_1exTl8wS3Ju5q5sydGux-94Dty4xGtfeyAEewG4FQCvv0vQy0b8zvuiN_EYw
AHy0nu8Ue-gMJrFBOgjTKr_pYfyChlaOjDhmay6vj0xaWvyFxdKOyiYlZSFQGGZIVMbSrhaa46WOf-dmcOS1a3mPjp9mFqqf77FZ-7JZ-Y76UQvV_Uel
}
' sprite decorator is defined once only - not once per sprite as per current puml files in stdlib
'==================================================================================================
' We define 1 or more sprite decorators in stdlib
'---------------------------------------------------
!unquoted procedure $SpriteDecorator($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="red")
rectangle $alias as "
<<$alias>>
$label
<color:$colour><$MySprite*$scale></color>
//<size:12>[$technology]</size>//
$description"
!endprocedure
'stdlib macros pass the sprite to the decorator - and the other parameters
'all this would happen in an all.puml file per sprite category
'==================================================================================================
!unquoted procedure $BATCH($alias, $description="", $label="", $technology="", $scale=1, $colour="red")
$SpriteDecorator($Batch, $alias, $description, $label, $technology, $scale, $colour)
!endprocedure
!unquoted procedure $ARVR($alias, $description="", $label="", $technology="", $scale=1, $colour="red")
$SpriteDecorator($Arvr, $alias, $description, $label, $technology, $scale, $colour)
!endprocedure
!unquoted procedure $SUMERIAN($alias, $description="", $label="", $technology="", $scale=1, $colour="red")
$SpriteDecorator($Sumerian, $alias, $description, $label, $technology, $scale, $colour)
!endprocedure
'user code
'================
$BATCH(BATCH, $scale=2)
$ARVR(ARVR, "description\non several lines", $scale=.9, $colour="blue")
$SUMERIAN(SUMERIAN, "other description", $label="sdsd", $scale=1.4)
'TODO: play with this to see if "Dynamic invocation" could be useful here?
' i.e. given
' a sprite
' a decorator function/procedure with params ($alias, $description, $label, $technology, $scale, $colour)
' %call_user_func("decorator", "$sprite")
' this would reduce the duplication even further in examples below
@enduml
|
3.4. Extensibility¶
So now we have a way for the user to specify any or all of the sprite parameters.
But what happens if we want to add new parameters in the future?
3.4.1. Option 1: Reserve Parameters¶
One option is to reserve parameters in the procedure definition:
!unquoted procedure $SpriteDecorator($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="red", $res1="", $res2="", $res3="", $res4="")
and used a function/procedure to map the new parameter feature to a reserved word.
We’re not smart enough to predict the future, and we don’t want to impose limits, so we won’t be doing this.
3.4.2. Option 2: Dynamic Invocation¶
See Standard Library - What We Have And What We Want for requirements for stdlib.
Let’s define 3 SpriteDecorator Procedures that change the sprite parameters per Standard Library - What We Have And What We Want, where each procedure adds more parameters than the previous one.
!unquoted procedure $SpriteDecorator($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="red")
!unquoted procedure $SpriteDecorator2($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="green", $shape="node")
!unquoted procedure $SpriteDecorator3($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="blue", $shape="cloud", $textsize="18")
When we define the procedure for the user to call e.g. $BATCH_DYN, we specify which SpriteDecorator to be used via $dynN dynamic invocation.
If at some point later, a new SpriteDecorator becomes available with same parameters but different processing, or with new parameters, then we can change this dynN to the new procedure.
3.4.2.1. User code¶
Parameters
can use ordered list of parameters up to the one they want to specify.
can use named arguments to specify only the parameter(s) they care about.
Existing code does not need to know or care that the SpriteDecorator has changed.
New code can use the new decorator functionality if desired.
Play with StdlibProposalCode online.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | @startuml
'all sprites in a category would be included in an all.puml file for that category
'==================================================================================================
'create equivalent of icons shown here https://github.com/awslabs/aws-icons-for-plantuml
sprite $Batch [64x64/16z] {
xLQ7bjim30CdzFzVtEV1iErPkJpT7iYm5aWDKERujFZ5Bp8YkSvM011VfMzSDy2Mw1JidbCGAtmllmbPuIkoImjyGUsyBV4LV95_Xny50bpW4uTRAjOKu81b
Xa0vbX3OKFG5C0IMNLyxXA_3PvW5hqHSOFBP_Ovk4036hYi0pJdTCgqD6A0g4FQ0hOwygxSikGOanw11AuvtomxXjNiRDECmn21xxTkJP0N4tdy1Gmu5T2GW
6ygFL_sqbx3NvA_FVtt_ri_F1CZNra-10TpNhvVr2KGcyVCOdoBySlpv-jC1ZSVveO36_Fwb0UASqGqG0QpfJgP2Eo60u59-fLVozhhdNk2WTeDpq2O6AAL_
uV7KGPNO2lya17gz1pMiD1VmFNH9IBLNe3xA3q07eNsMy_WdXESwU4jRmddEk-FUuPFjjthiqAEGVUz8rlqmsK1nhtYlklvp7vWRfka0jUNITUdTzgxFyzLx
-Ikh_YdmYr_y0G
}
'https://github.com/awslabs/aws-icons-for-plantuml/blob/master/dist/ARVR/ARVR.puml
sprite $Arvr [64x64/16z] {
xTG3WiH054NHzutP_th7RHkfsmnEdE1HZMZsIn0_DGDuuVsZJwnMVJ-57txuuKrsP4Tv1mjl3Nw43qZlo147VO9xPueyu8j1l3jm7V0GtPFWe8_UKzpL3rzc
TO4l0gZEzufCsDd-rnhoN2zKtKLoWk-bkHq--vabr0TypEy_WiwEmc9K7FATAd_fVDwOZygdU_uEF_pmLgUMA_wChkV1SavCc4LdXNVe2m
}
'https://github.com/awslabs/aws-icons-for-plantuml/blob/master/dist/ARVR/Sumerian.puml
sprite $Sumerian [64x64/16z] {
xPO5qkim38HN3FU_xuE29mMx-Hbtg4to6GIZxVVJhtvLLI-XbK2QJo6sVv90JA3SImUJRVuAjBeDl8zE0G2EyVy42d87NGOmGG0vVHuu7iRWZt4daBUWWW6j
8w_zNufuHES9KgxpKjr5o6CKQyh5uGi59BTfEuR1GHvEi6cu0N2sWE8sb99j03370L41CkryG9FQh6rTffOJlEWGLz-cbv5N4Pqh83Vf5THL67BA-qXltEu_
2XWrtrzlzZUfwuBCdjy_3ilGeY0Pgmj0NO5ehtb1vh9c0OhsaV_Qfa_hKUzKUDIs_eJgy7myMFEPLzinwd3nSQ0rpwYR_kiWmAgVmezmYuKSJ_94VZJDABad
y4EnAVcdyy4Xo6H_7g-02Se1oIVprMqKX_YdW9_AEtjtdVlNiykVmAS0Tjd_1exTl8wS3Ju5q5sydGux-94Dty4xGtfeyAEewG4FQCvv0vQy0b8zvuiN_EYw
AHy0nu8Ue-gMJrFBOgjTKr_pYfyChlaOjDhmay6vj0xaWvyFxdKOyiYlZSFQGGZIVMbSrhaa46WOf-dmcOS1a3mPjp9mFqqf77FZ-7JZ-Y76UQvV_Uel
}
'=============================DECORATORS==================================
' We define 1 or more sprite decorators in stdlib
' Define our decorators that we know now - and can easily define new ones in future with as manty new parameters
' as we want, that we don't even know about yet
' Let's say SpriteDecorator is defined month 1, SpriteDecorator2 is defined month 2, SpriteDecorator3 is defined month 3
'---------------------------------------------------
!unquoted procedure $SpriteDecorator($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="red")
rectangle $alias as "
<<$alias>>
$label
<color:$colour><$MySprite*$scale></color>
//<size:12>[$technology]</size>//
$description"
!endprocedure
'add a new shape parameter
'---------------------------------------------------
!unquoted procedure $SpriteDecorator2($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="green", $shape="node")
$shape $alias as "
<<$alias>>
$label
<color:$colour><$MySprite*$scale></color>
//<size:12>[$technology]</size>//
$description"
!endprocedure
'add a new shape parameter + a textsize parameter
'---------------------------------------------------
!unquoted procedure $SpriteDecorator3($MySprite, $alias, $description="", $label="", $technology="", $scale=1, $colour="blue", $shape="cloud", $textsize="18")
$shape $alias as "
<<$alias>>
$label
<color:$colour><$MySprite*$scale></color>
//<size:$textsize>[$technology]</size>//
$description "
!endprocedure
' test STATIC call of decorators with same icon
'---------------------------------------------------
$SpriteDecorator("$Batch", "static_dec1")
$SpriteDecorator2("$Batch", "static_dec2", $shape="node")
$SpriteDecorator3("$Batch", "static_dec3", $shape="cloud", $textsize="20")
' test DYNAMIC call of decorators with same icon
'---------------------------------------------------
'this does not work directly as $SpriteDecorator - so we do indirect as per following line
!$dyn = "$Sprite"+ "Decorator"
%invoke_procedure($dyn, "$Batch", "dynamic_dec1", "description", "label", "technology")
!$dyn2 = "$Sprite"+ "Decorator2"
%invoke_procedure($dyn2, "$Batch", "dynamic_dec2")
!$dyn3 = "$Sprite"+ "Decorator3"
%invoke_procedure($dyn3, "$Batch", "dynamic_dec3")
'=============================END DECORATORS==================================
' The beauty here is that for a given icon, we can change a given macro upwards (but not downwards)
' e.g. can change BATCH_DYN invoked prodedure from $dyn, to $dyn2, to $dyn3 etc... this gives:
' future proofing: user's code stays the same, but support for new params can be added
' ability to easily change the default decoration
!unquoted procedure $BATCH_DYN($alias, $description="", $label="", $technology="", $scale=1, $colour="red")
%invoke_procedure($dyn, "$Batch", $alias, $description, $label, $technology, $scale, $colour)
!endprocedure
!unquoted procedure $ARVR_DYN( $alias, $description="", $label="", $technology="", $scale=1, $colour="green", $shape="node")
%invoke_procedure($dyn2, "$Arvr", $alias, $description, $label, $technology, $scale, $colour, $shape)
!endprocedure
!unquoted procedure $SUMERIAN_DYN($alias, $description="", $label="", $technology="", $scale=1, $colour="blue", $shape="cloud", $textsize="30")
%invoke_procedure($dyn3, "$Sumerian", $alias, $description, $label, $technology, $scale, $colour, $shape, $textsize)
!endprocedure
' User can specify what they want in order, or via named arugments
$BATCH_DYN("batch_dyn_1", "desc", "label", "tech", 1)
$BATCH_DYN("batch_dyn_2", "desc", "label", "tech", 2, "brown")
$BATCH_DYN("batch_dyn_3", $scale=4)
$ARVR_DYN( "arvr_dyn_1")
$ARVR_DYN("arvr_dyn_2", "descsdfsdf", "label", "tech")
$ARVR_DYN( "arvr_dyn_3", $technology="mytech")
$SUMERIAN_DYN("sumerian_dyn_1", "descsdfsdf", "label", "tech")
$SUMERIAN_DYN("sumerian_dyn_2", "descsdfsdf", "label", "tech", 0.5, "pink", "node", 30)
@enduml
|