views:

205

answers:

4

Hi all,

I was wondering if anyone would be able to help me refactor some code that I wrote a while ago. I wrote a wrapper for a COM object that only excepted strings as input, so in good OOP practice I wrapped the string up in a function so that it was easier to build and call.

I was just wondering if anyone could think of a better way to do the following code.

   Public Function OpenTable(ByVal TablePath As String, Optional ByVal OpenAs As String = Nothing, _
            Optional ByVal Hide As Boolean = False, Optional ByVal AsReadOnly As Boolean = False, _
            Optional ByVal Interactive As Boolean = True, Optional ByVal Password As String = Nothing, _
            Optional ByVal NoIndex As Boolean = False, Optional ByVal ViewAutomatic As Boolean = True) As TableInfo

            If String.IsNullOrEmpty(TablePath) Then
                Throw New ArgumentNullException("TablePath", "TablePath cannot be null or empty")
            End If

            Dim Builder = New StringBuilder("Open Table ")
            Builder.AppendFormat("{0}{1}{2}", ControlChars.Quote, TablePath, ControlChars.Quote)

            If (Not String.IsNullOrEmpty(OpenAs)) Then Builder.AppendFormat(" as {0} ", OpenAs)
            If (Hide) Then Builder.Append(" Hide ")
            If (AsReadOnly) Then Builder.Append(" ReadOnly ")
            If (Interactive) Then Builder.Append(" Interactive ")
            If (Not String.IsNullOrEmpty(Password)) Then Builder.AppendFormat(" Password {0} ", Password)
            If (NoIndex) Then Builder.Append(" NoIndex ")
            If (ViewAutomatic) Then Builder.Append(" View Automatic ")

            MyComApp.Do(Builder.ToString)

            Dim FileInfo = New IO.FileInfo(TablePath)
            Return New TableInfo(FileInfo.Name.Substring(0, InStrRev(FileInfo.Name, ".") - 1))
        End Function

The amount of arguments that the function has to take is my biggest worry. This one is not too bad but there are some other functions that I may have to make in the future that will take a lot more arguments, so I'm mainly looking for better ways to build large argument functions.

Thanks.

A: 

Since i dont know your programming language, im gonna keep this to pseudo code, but my general answer is to use ann array as single parameter:

function OpenTable( options As array) {
    if (options is not array or options is empty) {
        Throw exception
    }
    return_string = "";
    if ( key is set ('readOnly', options) and is not empty) {
        return_string = return_string + ' readonly';
    }
    // repeat last 3 lines for all your params
}

Ok the last part of your function doesnt make sense to me, but the idea of array of params should come across i think. Good luck.

Alexander Morland
+2  A: 

One way to handle functions that can take lots of arguments is to create a new object type whose sole purpose is to hold arguments for that function. Then you create a new object of that type, set the properties as needed, then pass that one object reference to your OpenTable function.

Greg Hewgill
+3  A: 

In this case it seems many of the parameters are just 'configuration values' (which end up being strings), you could modify it to accept a single class for all the configuration that you prepare before the call and that will return you the string accordingly.

Something like

class COMConfiguration {
    private bool Hide = false;
    private bool AsReadOnly = false;
    //and so on...

    public void setHide(bool v) { Hide = v; }

    //only setters

    public string getConfigString() {
        StringBuilder sb = new StringBuilder();
        if (Hide) { sb.Append(" Hide "); }
        if (AsReadOnly) { sb.Append(" ReadOnly "); }
        //and so on
        return sb.ToString()
    }
}
Vinko Vrsalovic
A: 

You can switch all your boolean parameters to a single parameter of an enum type, marked as Flags. Here's an example declaration:

' Define an Enum with FlagsAttribute.
<FlagsAttribute( )> _
Enum TableOptions as Short
    Hide = 1
    AsReadOnly = 2
    Interactive = 4
    NoIndex = 8
    ViewAutomatic = 16
End Enum
Franci Penov
The problem is that you can have multiple options true or false. So you can have both AsReadOnly and Interactive passed to the function so just one enum won't work
Nathan W
That's exaclty the reason I said the enum should be marked with the Flags attribute.
Franci Penov
ahh I see, sorry I didn't read the link. Thanks
Nathan W