Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How many parameters are too many parameters?
#1
Another of my Steve's Overengineered Routines:

Code: (Select All)
Option _Explicit


Screen _NewImage(1280, 720, 32)
$Color:32

'Box (Mode As Integer, X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer, Caption As String, _
' FontColor As _Unsigned Long, FontBackground As _Unsigned Long, BoxColor As _Unsigned Long, _
' BoxHighLight As _Unsigned Long, XOffset As Integer, YOffset As Integer
'Mode 0 (or any unsupported number) will tell the box to size itself from X1,Y1 to X2,Y2
'Mode 1 will tell the box to autosize itself according to whatever text is placed within it.
'Mode 2 will tell the box to use X2 and Y2 as relative coordinates and not absolute coordinates. (Width and Height of box.)
'Mode 3 will tell the box to autocenter text with X2, Y2 being absolute coordinates.
'Mode 4 will tell the box to autocenter text with X2, Y2 being relative coordinates. (Width and Height of box.)
'X1/Y1 carries the X/Y location of where we want to place our box on the screen.
'X2/Y2 is the X/Y boundry of our box on the screen, depending on our mode.
'Caption is the text that we want our box to contain.
'FontColor is our font color for our caption and FontBackground is the font background color for our caption
'BoxColor is our box color and BoxHighlight is our box highligh colors

'XOffset/YOFFSET is used to offset our text # pixels from the X1/Y1 position.

Dim i As Long

For i = 0 To 4
Print "Showcasing diffferent modes for Box. This is mode #"; i
Box i, 100, 100, 200, 200, "Hello World", Red, Blue, Gold, Silver, 0, 0
Sleep
Cls
Next

Sub Box (Mode As Integer, X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer, Caption As String, FontColor As _Unsigned Long, FontBackground As _Unsigned Long, BoxColor As _Unsigned Long, BoxHighLight As _Unsigned Long, XOffset As Integer, YOffset As Integer)
'This is an upgrade version of my original Button routine.
'It's more versitile (but complex) than the original.
'Mode 0 (or any unsupported number) will tell the box to size itself from X1,Y1 to X2,Y2
'Mode 1 will tell the box to autosize itself according to whatever text is placed within it.
'Mode 2 will tell the box to use X2 and Y2 as relative coordinates and not absolute coordinates.
'Mode 3 will tell the box to autocenter text with X2, Y2 being absolute coordinates.
'Mode 4 will tell the box to autocenter text with X2, Y2 being relative coordinates.
'Mode otherwise is unused, but available for expanded functionality.
'X1 carries the X location of where we want to place our box on the screen.
'Y2 carries the Y location of where we want to place our box on the screen.
'X2 is the X boundry of our box on the screen, depending on our mode.
'Y2 is the Y boundry of our box on the screen, depending on our mode.

'Caption is the text that we want our box to contain.

'FontColor is our font color for our caption
'FontBackground is the font background color for our caption
'NOTE: IF FONTCOLOR OR FONTBACKGROUND IS SET TO ZERO, THEY WILL **NOT** AFFECT THE COLOR BEHIND THEM.
'This can be used to mimic the function of _KEEPBACKGROUND, _FILLBACKGROUND, or _ONLYBACKGROUND


'BoxColor is our box color
'BoxHighlight is our box highligh colors
'NOTE: SAME WITH BOXCOLOR AND BOXHIGHLIGHT. IF SET TO ZERO, THEY WILL HAVE **NO** COLOR AT ALL TO THEM, AND WILL NOT AFFECT THE BACKGROUND OF ANYTHING BEHIND THEM.

'XOffset is used to offset our text # pixels from the X1 top.
'YOffset is used to offset our text # pixels from the Y1 top.
'These can be used to place our text wherever we want on our box.
'But remember, if Mode = 3 or 4, the box will autocenter the text and ignore these parameters completely.

Dim BoxBlack As _Unsigned Long
Dim As Long dc, bg, cw, ch
dc& = _DefaultColor: bg& = _BackgroundColor
BoxBlack = _RGB32(0, 0, 0)
cw = _PrintWidth(Caption): ch = _FontHeight

Select Case Mode
Case 0
'We use the X2, Y2 coordinates provided as absolute coordinates
Case 1
X2 = X1 + cw + 8
Y2 = Y1 + ch + 8
XOffset = 5: YOffset = 5
Case 2
X2 = X1 + X2
Y2 = Y1 + Y2
Case 3
XOffset = (X2 - X1 - cw) \ 2
YOffset = (Y2 - Y1 - ch) \ 2
Case 4
X2 = X1 + X2
Y2 = Y1 + Y2
XOffset = (X2 - X1 - cw) \ 2
YOffset = (Y2 - Y1 - ch) \ 2
End Select
Line (X1, Y1)-(X2, Y2), BoxBlack, BF
Line (X1 + 1, Y1 + 1)-(X2 - 1, Y2 - 1), BoxHighLight, B
Line (X1 + 2, Y1 + 2)-(X2 - 2, Y2 - 2), BoxHighLight, B
Line (X1 + 3, Y1 + 3)-(X2 - 3, Y2 - 3), BoxBlack, B
Line (X1, Y1)-(X1 + 3, Y1 + 3), BoxBlack
Line (X2, Y1)-(X2 - 3, Y1 + 3), BoxBlack
Line (X1, Y2)-(X1 + 3, Y2 - 3), BoxBlack
Line (X2, Y2)-(X2 - 3, Y2 - 3), BoxBlack
Line (X1 + 3, Y1 + 3)-(X2 - 3, Y2 - 3), BoxColor, BF
Color FontColor, FontBackground
_PrintString (X1 + XOffset, Y1 + YOffset), Caption$
Color dc&, bg&
End Sub




Function BoxImage& (Mode As Integer, X As Integer, Y As Integer, Caption As String, FontColor As _Unsigned Long, FontBackground As _Unsigned Long, BoxColor As _Unsigned Long, BoxHighLight As _Unsigned Long, XOffset As Integer, YOffset As Integer)
'This creates our box as an image so we can manipulate it however we wish before placing it on the screen.

'Mode 0 will tell the box to draw itself X,Y size, and autocenter the text.
'Mode 1 will tell the box to autosize itself according to whatever text is placed within it.
'Mode 2 will tell the box to draw itself X,Y size, and place the text at the offsets.

'Mode otherwise is unused, but available for expanded functionality.

'Caption is the text that we want our box to contain.

'FontColor is our font color for our caption
'FontBackground is the font background color for our caption
'NOTE: IF FONTCOLOR OR FONTBACKGROUND IS SET TO ZERO, THEY WILL **NOT** AFFECT THE COLOR BEHIND THEM.
'This can be used to mimic the function of _KEEPBACKGROUND, _FILLBACKGROUND, or _ONLYBACKGROUND

'BoxColor is our box color
'BoxHighlight is our box highligh colors
'NOTE: SAME WITH BOXCOLOR AND BOXHIGHLIGHT. IF SET TO ZERO, THEY WILL HAVE **NO** COLOR AT ALL TO THEM, AND WILL NOT AFFECT THE BACKGROUND OF ANYTHING BEHIND THEM.

'XOffset is used to offset our text # pixels from the X1 top.
'YOffset is used to offset our text # pixels from the Y1 top.
'These can be used to place our text wherever we want on our box.
'But remember, if Mode = 3 or 4, the box will autocenter the text and ignore these parameters completely.

Dim BoxBlack As _Unsigned Long
Dim As Long dc, bg, cw, ch
Dim As Long X1, Y1, X2, Y2, tempBoxImage
dc& = _DefaultColor: bg& = _BackgroundColor
BoxBlack = _RGB32(0, 0, 0)

cw = _PrintWidth(Caption): ch = _FontHeight

X1 = 0: Y1 = 0
X2 = X: Y2 = Y

Select Case Mode
Case 0
X2 = X1 + cw + 8
Y2 = Y1 + ch + 8
XOffset = 5: YOffset = 5
Case 2
XOffset = (X2 - cw) \ 2
YOffset = (Y2 - ch) \ 2
End Select
tempBoxImage& = _NewImage(X, Y, 32)
_Dest tempBoxImage&
Line (X1, Y1)-(X2, Y2), BoxBlack, BF
Line (X1 + 1, Y1 + 1)-(X2 - 1, Y2 - 1), BoxHighLight, B
Line (X1 + 2, Y1 + 2)-(X2 - 2, Y2 - 2), BoxHighLight, B
Line (X1 + 3, Y1 + 3)-(X2 - 3, Y2 - 3), BoxBlack, B
Line (X1, Y1)-(X1 + 3, Y1 + 3), BoxBlack
Line (X2, Y1)-(X2 - 3, Y1 + 3), BoxBlack
Line (X1, Y2)-(X1 + 3, Y2 - 3), BoxBlack
Line (X2, Y2)-(X2 - 3, Y2 - 3), BoxBlack
Line (X1 + 3, Y1 + 3)-(X2 - 3, Y2 - 3), BoxColor, BF
Color FontColor, FontBackground
_PrintString (X1 + XOffset, Y1 + YOffset), Caption$
Color dc&, bg&
_Dest 0
BoxImage = tempBoxImage
End Function

Function TextScreenToImage256& (image&)
Dim As Long d, s, i, f, fw, fh, w, h, l
Dim As Long tempScreen, Screen0to256
Dim m As _MEM, b As _Unsigned _Byte, t As String * 1
Dim o As _Offset

d& = _Dest: s& = _Source
Dim Plt(15) As Long
_Source image&: _Dest image&
For i = 0 To 15: Plt(i) = _PaletteColor(i, image&): Next
f& = _Font(image&)
_Font f&
fw& = _FontWidth
fh& = _FontHeight
w& = _Width * _FontWidth
h& = _Height * _FontHeight '+ _HEIGHT
l& = (_Width * _Height) * 2 'The screen is width * height in pixels. (80X25) = 2000 X 2 bytes each = 4000 total bytes to hold a page of screen 0 text and color
tempScreen& = _NewImage(w&, h& + _Height, 256)
Screen0to256& = _NewImage(w&, h&, 256)

m = _MemImage(image&)
o = m.OFFSET

_Dest (tempScreen&)
For i = 0 To 15: _PaletteColor i, Plt(i): Next
_Font f&

For i = 0 To l& - 2 Step 2
_MemGet m, m.OFFSET + i, t
_MemGet m, m.OFFSET + i + 1, b
If b > 127 Then b = b - 128
Color b Mod 16, b \ 16
Print t;
Next
_PutImage , tempScreen&, Screen0to256&, (0, 0)-(w&, h&)
_FreeImage tempScreen&
_Dest d&: _Source s&
_MemFree m
TextScreenToImage256 = Screen0to256&
End Function

Function TextScreenToImage32& (image&)
Dim As Long d, s, i, f, fw, fh, w, h, l, fgc, bgc
Dim As Long tempScreen, Screen0To32
d& = _Dest: s& = _Source
Dim Plt(15) As Long
_Source image&
For i = 0 To 15: Plt(i) = _PaletteColor(i, image&): Next
f& = _Font(image&)
_Font f&
fw& = _FontWidth
fh& = _FontHeight
w& = _Width * _FontWidth
h& = _Height * _FontHeight '+ _HEIGHT
l& = (_Width * _Height) * 2 'The screen is width * height in pixels. (80X25) = 2000 X 2 bytes each = 4000 total bytes to hold a page of screen 0 text and color
tempScreen& = _NewImage(w&, h& + _Height, 32)
Screen0To32& = _NewImage(w&, h&, 32)
_Dest tempScreen&

Dim m As _MEM, b As _Unsigned _Byte, t As String * 1
Dim o As _Offset
m = _MemImage(image&)
o = m.OFFSET

_Font f&

For i = 0 To l& - 2 Step 2
_MemGet m, m.OFFSET + i, t
_MemGet m, m.OFFSET + i + 1, b
If b > 127 Then b = b - 128
fgc = b Mod 16: bgc = b \ 16
Color _RGB32(_Red(fgc, image&), _Green(fgc, image&), _Blue(fgc, image&)), _RGB32(_Red(bgc, image&), _Green(bgc, image&), _Blue(bgc, image&))
Print t;
Next
_PutImage , tempScreen&, Screen0To32&, (0, 0)-(w&, h&)
_FreeImage tempScreen&
_Dest d&: _Source s&
_MemFree m
TextScreenToImage32 = Screen0To32&
End Function

Function BinaryStringSearch (search$, Array() As String)
'These routines work with actual indexes, so we can search from Array(-10 to 10), if we want to.
'When the search string is found, it'll return a value = to the index proper.
'When it's not found, it'll return a value LESS THAN the LBOUND limit of the array,
'And the point where the string WOULD'VE appeared, if it existed, is after the shared variable LastIndex

BinaryStringSearch = BinaryStringSearchSome(search$, Array(), LBound(Array), UBound(Array))
End Function

Function BinaryStringSearchSome (search$, Array() As String, StartIndex As Long, EndIndex As Long)
'These routines work with actual indexes, so we can search from Array(-10 to 10), if we want to.
'When the search string is found, it'll return a value = to the index proper.
'When it's not found, it'll return a value LESS THAN the LBOUND limit of the array,
'And the point where the string WOULD'VE appeared, if it existed, is after the shared variable LastIndex
Dim As Long min, max, compare, LastIndex, found
Dim As _Float gap
min = StartIndex
max = EndIndex

Do
gap = (max + min) \ 2
compare = _StrCmp(search$, Array(gap))
If compare > 0 Then
min = gap + 1
ElseIf compare < 0 Then
max = gap - 1
Else
BinaryStringSearchSome = gap
Exit Function
End If
If max - min < 1 Then
If search$ = Array(min) Then
BinaryStringSearchSome = min
Else
BinaryStringSearchSome = LBound(Array) - 1
If search$ < Array(min) Then
LastIndex = min - 1
Else
LastIndex = min
End If
End If
found = -1
End If
Loop Until found
End Function

Sub StringSortSome (Array() As String, StartIndex As Long, EndIndex As Long)
Dim As Long min, max, i, swapped
Dim As _Float gap
min = StartIndex
max = EndIndex

gap = EndIndex - StartIndex + 1
Do
gap = 10 * gap \ 13
If gap < 1 Then gap = 1
i = StartIndex
swapped = 0
Do
If _StrCmp(Array(i), Array(i + gap)) > 0 Then
Swap Array(i), Array(i + gap)
swapped = -1
End If
i = i + 1
Loop Until i + gap > EndIndex
Loop Until swapped = 0 And gap = 1
End Sub

Sub StringSort (Array() As String)
StringSortSome Array(), LBound(Array), UBound(Array)
End Sub

Only 12 parameters in this one. (The one that turns the box into an image is even more!)

So my question is: How many parameters are TOO MANY parameters? Little routines like this one can be expanded in sooo many different ways. (A parameter for the width of the border/highlight. One for if we want shading, and one for what shade of shading, and which direction it should shade in. One for a rotation, or a scale factor, or if we allow blending or not...)

Do you guys have some hard and fast limit that you tend to use for how many parameters you attach to a sub or function? I'm just curious about what other folks opinions are for this type of ultra-versatile routine.
Reply
#2
In my opinion, ditch the crazy amount of parameters and instead do a UDT that contains the information and pass that. Like how Windows API does a lot of their calls.
Tread on those who tread on you

Reply
#3
(10-19-2023, 11:27 AM)SpriggsySpriggs Wrote: In my opinion, ditch the crazy amount of parameters and instead do a UDT that contains the information and pass that. Like how Windows API does a lot of their calls.

+1 That is one fine way to do it.

Too many? It gets crazy with modes by number who wants to remember a bunch of codes for one routine?
But I can understand the desire to be as flexible as possible, who wants to write mostly redundant code? like a sort routine for every data type and still can't do UDTs.
b = b + ...
Reply
#4
The problem with UDTs and sorts is exactly which element of the UDT are you trying to sort by?  If you're getting to the point where you need to sort like that, then you need to check out my old QBDbase stuff.  It allows sorting across multiple elements in a UDT, so you can set priority on which element takes precedence over what other ones.  Smile

As for remembering the codes, the easiest way there is to set a CONST to a helpful name and use it.  CONST Absolute_Coordinate, Absolute_Center, Auto_Resize, Relational_Coordinate, Relational_Center....    Smile

The main problem I have with using UDTs as parameters is that values tend to accidently bleed over from one call to the next, as folks won't fill out each and every value before making the call.

"All I need is X/Y and center...  I can skip this other stuff!"     
....  compile and run later....
"WTH!  Why isn't this working as I expected?!!"
Reply
#5
You should give C++ and Pure Basic programmers more credit for knowing what they're doing. Rolleyes

In Pure Basic there's no choice, must use pointer to pass an UDT variable to a subprogram. But it looks like folks that use that programming language prefer that over a subprogram that takes 30 parameters and sometimes only four or five of the optional ones are chosen. IIRC cannot have commas in the midst for an user procedure call in that BASIC dialect, but could have optional parameters from the end of the parameter list.

Good programming practice is to allocate a "dummy" UDT variable which has its fields set to "defaults" or cleared out. Then before calling the subprogram that will work with an UDT variable, first set that variable to the value of the "dummy". But not everybody will be eager to do that, or could forget to do it.

What I know is, I don't like much more than 10 parameters to a call to any subprogram. I remember Ethan Winer's book for the "full-blown" `Editor` subprogram. Somewhere in the book, however, he offered a cut-down version which doesn't care about screen position and colors and a few other things. I much preferred the 4-parameter `Editor`. I used it a lot, until I ran into trouble with a QB64 program. This program inexplicably returned many junk keys and despite my efforts to fix it, `Editor` was unusable for that purpose.
Reply
#6
Not all that difficult to adapt the code to a User Defined Type scheme, and you can make awesome shorthand routines:

Code: (Select All)
'not a whole program just a block to edit the original
Type box_type
    Mode As Integer
    X1 As Integer
    Y1 As Integer
    X2 As Integer
    Y2 As Integer
    Caption As String
    FontColor As _Unsigned Long
    FontBackground As _Unsigned Long
    BoxColor As _Unsigned Long
    BoxHighLight As _Unsigned Long
    XOffset As Integer
    YOffset As Integer
End Type
Dim bx As box_type
Screen _NewImage(1280, 720, 32)
$Color:32

Dim i As Long
For i = 0 To 4
    Print "Showcasing diffferent modes for Box.  This is mode #"; i
    Set_Box bx, i, 100, 100, 200, 200, "Hello World", Red, Blue, Gold, Silver, 0, 0

   if i = 4 then  Change_BoxCaption Bx,"Bye Bye"
    Box bx
    Sleep
    Cls
Next

Sub Set_Box (TheBox As box_type, Mode As Integer, X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer, Caption As String, FontColor As _Unsigned Long, FontBackground As _Unsigned Long, BoxColor As _Unsigned Long, BoxHighLight As _Unsigned Long, XOffset As Integer, YOffset As Integer)
    TheBox.Mode = Mode
    TheBox.X1 = X1
    TheBox.Y1 = Y1
    TheBox.X2 = X2
    TheBox.Y2 = Y2
    TheBox.Caption = Caption
    TheBox.FontColor = FontColor
    TheBox.FontBackground = FontBackground
    TheBox.BoxColor = BoxColor
    TheBox.BoxHighLight = BoxHighLight
    TheBox.XOffset = XOffset
    TheBox.YOffset = YOffset
End Sub

Sub Set_BoxMode (TheBox As box_type, mode As Integer)
    If mode > 0 And mode < 5 Then
        TheBox.Mode = mode
    Else
        TheBox.Mode = 0
    End If
End Sub
Sub Change_BoxCaption (TheBox As box_type, caption As String)
    TheBox.Caption = caption
End Sub
Sub move_Box (TheBox As box_type, xmove As Integer, ymove As Integer)
    TheBox.X1 = TheBox.X1 + xmove
    TheBox.Y1 = TheBox.Y1 + ymove
    TheBox.X2 = TheBox.X2 + xmove
    TheBox.Y2 = TheBox.Y2 + ymove
End Sub

Sub Box (TheBox As box_type)
    Dim Mode As Integer, X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer, Caption As String, FontColor As _Unsigned Long, FontBackground As _Unsigned Long, BoxColor As _Unsigned Long, BoxHighLight As _Unsigned Long, XOffset As Integer, YOffset As Integer
    Mode = TheBox.Mode
    X1 = TheBox.X1
    Y1 = TheBox.Y1
    X2 = TheBox.X2
    Y2 = TheBox.Y2
    Caption = TheBox.Caption
    FontColor = TheBox.FontColor
    FontBackground = TheBox.FontBackground
    BoxColor = TheBox.BoxColor
    BoxHighLight = TheBox.BoxHighLight
    XOffset = TheBox.XOffset
    YOffset = TheBox.YOffset
  '  ...
Reply




Users browsing this thread: 2 Guest(s)