-Edit- This is for a finance API I am designing. I am in the process of creating some empty classes, getting a feel for the general structure. My primary concern is designing a pleasant user experience without requiring a manual to explain how to use it. -End Edit-
I have been scratching my head trying to think of the best way to go about designing a specific class. I will create a general example to illustrate.
Namespace SomeNamespace
Public Class Results
Public a1 as Integer
Public a2 as Integer
...
Public b1 as Integer
...
Public z1 as Integer
End Class
End Namespace
The example above is generic, but the point is there are many values within the class. The letter in the variable name represents a similar group of results. The "a" results are similar, "b" similar, etc. I had thought to make a class for each type of result value (since they are a type of result, but separate concepts from each other) within the Results class such as...
Public Class Results
Class a
Public a1 as Integer
End Class
Class b ... End Class
End Class
The problem with this is that it is not explicit that when a person uses the class
Dim ResultObject as new SomeNamespace.Results.a()
the Results object would have to be instantiated first, because any of the sub-classes a,b, etc would rely on the Results object. But the user would see the objects a,b, etc and perhaps not know that they must create the parent object first.
I thought about making the classes separate and each constructor would create a Result object, but that seems backwards logically. Any Advice? Sorry if it was confusing.
Why not make an Abstract class Result and create an inheritance structure ResultTypeA, ResultTypeB etc.? With no details on the problem it is really hard to give a meaningfull answer.
Why not use a single 2-dimensional integer array, where the first index is the result class (i.e. letter 'a' or 'b' etc), and the second index is the result number (i.e. a1 or z2 etc)?
Two quick recommendations.
1) In classes, don't expose your fields. Only expose methods and properties. If you're using auto implemented properties this is done by just adding the Property keyword in your declaration. Otherwise, declare your field as private and the property that exposes it as public:
Public Class Foo
Private _V1 As Integer ' Backing field
Public Property V2 As Integer ' Auto Property
Public Property V1 As Integer ' With backing field
Get
Return _V1
End Get
Set (Value as Integer)
_V1 = value
End Set
End Property
End Class
2) Don't nest your class declarations. Instead of
Public Class Results
Class a
Public a1 as Integer
End Class
Class b ... End Class
End Class
Do the following:
Public Class Results
Public Property A1 As A
Public Property B1 As B
End Class
Public Class A
Public Property A1 As Integer
End Class
Public Class B
Public Property B1 As Integer
End Class
For naming conventions, you should name your properties as nouns and methods as verbs. I regarding your ordering question, I recommend starting with the category (noun) and then adding adjectives after it in increasingly specific terms:
Property NameFirst As String
Property NameLast As String
Property ContactEmail As String
Property ContactPhoneHome As String
Property ContactPhoneWork As String
Related
I have a class that I would like to extend by defining a new class that contains the first class as a public property, as well as additional added properties. However, the class that I'm extending has multiple derived types, which should be treated the same in the extension class.
Below is an example of what I am trying to do:
Public Class ClassA
End Class
Public Class ClassB
Inherits ClassA
End Class
Public Class ClassC
Inherits ClassA
End Class
Public Class BaseExtended
Public Property Foo As ClassA
Public Property ExtendedMetaData1 As Double
Public Property ExtendedMetaData12 As Integer
End Class
Public Class DerivedExtendedB
Inherits BaseExtended
Public Property Foo As ClassB
End Class
Public Class DerivedExtendedC
Inherits BaseExtended
Public Property Foo As ClassC
End Class
The code that uses an instance of any of the 'extended' classes would then need use that instance appropriately depending on it's type. There would be many cases where the property 'Foo' needs to be accessed and modified outside of the class that it belongs to.
If I were to implement something like what I have shown above, that would require that I first cast it to the required type before accessing or modifying it. Ideally I would like to do that inside the 'DerivedExtended' class; The alternative, I think, would be to duplicate code to cast that property would [hundreds of times] in the client code.
Private Sub ClientUsesObject(bar As BaseExtended)
' Perform a task that is agnostic Foo type
' Would not require that Foo be cast to any specific type
If bar.GetType() Is GetType(DerivedExtendedB) Then
Dim barCast As DerivedExtendedB = DirectCast(bar, DerivedExtendedB)
' Perform task that requires Foo to be of type ClassB
ElseIf bar.GetType() Is GetType(DerivedExtendedC) Then
Dim barCast As DerivedExtendedC = DirectCast(bar, DerivedExtendedC)
' Perform task that requires Foo to be of type ClassC
End If
End Sub
What I'm looking for is advice outlining or describing a design pattern that can handle this situation. I've searched for quite a while, and have not been able to find any examples that solve this problem.
I realize that this may be somewhat of an "XY" problem. I'm working with existing code that simply assumes all instances are of the same derived type (when in fact some instances are of the other derived type). As such, the existing code does not work. To me what I've tried to outline above seems like the most straightforward path, but I'm open to alternative if this is just the wrong approach.
This pattern of type covariance in derived classes is the canonical reason for what is called in C++ the "Curiously Recurring Template Pattern" and has been called in .NET the "Curiously Recurring Generic Pattern." I believe it's also sometimes referred to as "F-Bounded Polymorphism" (not a computer scientist, so I might have the reference wrong).
You can write a base class like this:
Public Class Base(Of TDerived As Base)
Public Overridable Property foo As TDerived
End Class
And then use it like this:
Public Class MyDerived
Inherits Base(Of MyDerived)
End Class
Then, the derived class has a property foo whose type is MyDerived. No casting required by clients.
However, this has some limitations. It works best when you don't need to switch back and forth between derived and base. There is no one Base, so you can't declare instances of it. If you want to be able to declare something as Base, then you end up needing to fall back on a non-generic base class. This will still work well for certain usage patterns where you don't need to convert from base to derived, but otherwise you run right back into the casting problems you are trying to avoid.
Eric Lippert has written a bit about this pattern. He's always interesting to read, so I'd recommend looking up his commentary.
Another alternative to consider, if the generic approach doesn't work for you, is code generation. You can use T4 templates to process a compact description of what your code should be, and generate the code files from them. A long list of casts is less tedious if you only write the machinery to generate it, you don't write them all out explicitly.
Ok, so this kind of follows after a previous question that I've asked involving structures and classes. So referencing this question (and I am using classes now for the base) I have one member of the class that is an array (and I know that I have to declare it without dimensions) that as part of the constructor I want it to define the dimensions of the array. When I was initially trying to do the ReDim the compiler was unhappy because I was declaring the member as ReadOnly. While what I'm doing with the array has it's own question of feasibility to it that's not what I'm asking about as it raised a different issue that I must answer first.
Is there a way to make members of a class/structure read only outside of the class/structure but modifiable with in the class/structure without having to use properties or internal functions/subs to gain the read access?
Basically like declaring the member private but you can at least read the member outside the class/structure. Just not anything else.
You can do something like this
Private _some As String
Public Property Some As String
Get
Return _some
End Get
Private Set(value As String)
_some = value
End Set
End Property
No. On its own, there is no way to make a class field public for reading, but private for writing. Accessibility modifiers on a field affect both read and write.
The cleanest way to do what you want is to define a private field in your class, and define a public property getter:
Private _dummy As String
Public Property Dummy() As String
Get
Return _dummy
End Get
End Property
Granted, it would be nice to be able to express this more succinctly, as is possible with C# using auto-implemented properties:
public string Dummy {get; private set;}
Assume we have a class called "MyClass"
Public Class MyClass
End Class
this class has a function called "My function"
Public Class MyClass
Public Function MyFunction()
End Function
End Class
This class has been implemented for some time and its been working fine. Now we need to change the implementation of the function "MyFunction". One option would be to open the source code and change it there. But I'm guessing there has to be a better approach.
Inheritance comes to mind but I don't want to change the derived classes name. I want the name of the class to still remain "MyClass", But I'm guessing the code below will cause an error:
Public Class MyClass
Inherits MyClass
Public Function MyFunction()
End Function
End Class
In other words I'm trying to create a new version of the old class by keeping most of the members the same but just changing a few functions.
To explain the project as a whole, The program is meant for structural design. What it does it designs structural components (i.e columns, beams, slabs, ...). The design procedures are specified by 3rd parties (government regulations). For example:
In the year 2007 government regulations specified that column dimensions are to satisfy the equation F:
H*B < Fy^2/L
In the year 2008 they introduced a new function G and they say column dimensions must satisfy this new function:
H*B^2 < Fy^0.5/E+Alpha^2/L
Where H and B are column dimensions.
What I don't want to do is to open the source code every year and make these changes. I want to somehow override the functions that need to be changed without opening the source.
Any Ideas?
The code is generally not supposed to be changed over time. That is - if you wrote code that is guaranteed to break after 2 weeks by itself, you probably should reconsider your design.
As you rules/regulations come out, you usually update your input data (in a form of XML, or a relational database for large amounts of data), and your program would automatically pick those up.
The only case you would update your program under this scenario is when new type of regulations come out. But even in this case the changes are usually minimal.
A good anti-pattern example for this - you have 500 forms, each of them has 500 lines of code, so that's 250000 lines of code in your UI layer. New regulations come out that requires changing 50% of the code in each form. Your impact is 125000, which at 40 lines of code per day would take 8.5 developer-years.
A solution to this would be having a change of 100 lines spread across all forms, adding 1 line in each, or leaving everything as is. Also there will be a data load/conversion procedure from a government/other file, which populates your database in the proper format, updating the values or adding new ones. There may be 10 lines of change in that program, but that's about it, 3 days worth of work, if you believe in 40 LoC per day. Otherwise it still falls under 2 weeks of developer's time.
Depending on how you implement it, the benefit of this approach could be that you support old standards as well, so older input can be matched and production reports can be generated. It is a good practice to be able to back-date your reports, cause sometimes there are issues in report code left unnoticed for months before being discovered.
EDIT: A more structured approach to what I suggested in the comments would be storing expression trees in the DB. Most simple form of it is just a linear workflow, using postfix notation (single table). For example A, B, + C - is equivalent to A + B - C. You can then have a user interface for some configuration tool, which only allows user to input values and functions that are applicable. This is assuming applicable values are also stored in DB as parameters (one structural component can have 0...N of them).
Inheritance can do what you want but you need to create a new ancestor, not descendant.
Change the name of the original class to something that denotes that it is a base class. Also, add the MustInherit modifier to the class and Overridable to any of the methods or properties that you may need to override.
One thing to watch for is Private members in this base class. Any members that need to be accessible from the descendant class cannot be Private and must be changed to Protected.
The original class looks like this.
Public MustInherit Class MyBaseClass
Public Overridable Function MyFunction() As String
' code...
End Function
Public Overridable Function AnotherFunction() As String
' code...
End Function
End Class
Now create a new class with the original class's name which inherits from the base class. Override just the members that need to be different.
Public Class MyClass
Inherits MyBaseClass
Public Overrides Function MyFunction() As String
' new code...
End Function
End Class
That will get you started. The Template Pattern will allow you to do more fine grained code changes where only parts of a method need to be changed.
The formula is a bit complicated and you'll still need to change some code unless you store these in a database somehow.
An option would be to use inheritance with a factory method.
Public Class BaseClass
Public MustOverride Function MyFunction()
Public Function GetInstance(ByVal year As Integer) As BaseClass
If year = 2007 Then Return New Class2007()
If Year = 2008 Then Return New Class2008()
End Function
End Class
Public Class Class2007
Inherits BaseClass
Public Overrides Function MyFunction()
' H*B < Fy^2/L
End Function
End Class
Public Class Class2008
Inherits BaseClass
Public Overrides Function MyFunction()
' H*B^2 < Fy^0.5/E+Alpha^2/L
End Function
End Class
then, everywhere in your code you use BaseClass never knowing that Class2007 and Class2008 exists
Dim o As BaseClass
o = BaseClass.GetInstance(2007)
o.MyFunction()
Depending on the need, this can also be done with interface.
If you need to store the formulas in the database as string, you'll need to get a parser and this can also be found using 3rd party library. https://stackoverflow.com/questions/1387430/recommended-math-library-for-c-net
I have read several questions on here and it appears that the general consensus is that an interface is not required for every class in a project. I have read posts like this: Is it the best practice to extract an interface for every class?.
I want to know how this applies to the .NET framework classes. I believe that all of the classes I have looked at either inherit from an abstract class e.g. SQLConnection inherits from dbConnection or implement and interface e.g. the Component class implements the IComponent interface.
I have a copy of Reflector, which I downloaded two months ago and I am awaiting the license (paid the fee recently). When I start to step through the code (using Reflector); am I going to see code like this:
Public Class Foo
Public Name As String
Public Property NameProperty()
Get
Return Name
End Get
Set(value)
Name = value
End Set
End Property
Public Shared Sub Main()
Dim f As Foo = New Foo
f.NameProperty = "Ian"
End Sub
End Class
rather than code like this:
Public Class Foo
Implements IFoo
Public Name As String
Public Property NameProperty() Implements IFoo.NameProperty
Get
Return Name
End Get
Set(value)
Name = value
End Set
End Property
Public Shared Sub Main()
Dim f As IFoo = New Foo
f.NameProperty = "Ian"
End Sub
End Class
Public Interface IFoo
Property NameProperty()
End Interface
Notice that there is an Interface used in the second code fragment. I am still struggling to understand when it is suitable not to use interfaces. Some developers say never. I suppose some of it is subjective.
As someone who strives to do things the right way, I struggle with this every time I start a new project. I've come to realize that it's mostly subjective; like saying "on which days is OK to not take a shower".
Of course it provides abstraction, improves testability, etc., but it can lead to unnecessary "class explosion". Adding interfaces to ancillary internal classes does more harm than good in my experience. I occasionally open a small project I did years ago and am shocked my the endless list of classes ... over-engineering!
As a rule, I use interfaces for APIs in class libraries. Other than that, I add them if time allows, or I have a special need to clarify how a section of code is supposed to be called by client code.
I have been charged with porting a VB6 project into VB.NET. In vb6, if you were in a class separate to a particular variable, you could access that variable easily:
Public Class Foo
Public k As Integer
End Class
Public Class Bar
k = 12
End Class
In VB.NET, my understanding is that before you can use a variable in another class, you must declare a new instance of it:
Dim foobar As New Foo
This would be fine, but I have to access these variables from different classes and every time I declare a new instance, it wipes all old values from the variables, which I need. Can anybody help? I tried using Inherits statements but they presented many problems.
Thanks.
Nick
Your're looking for the shared keyword. This makes the member available to other classes without having to have an instance of your class. See MSDN for more info
For the port just use Public module like you would in vb6
Public Module Foo
Public k As Integer
End Module
Public Module Bar
Foo.k = 12
End Module
Its not good practice but it will help you do your first pass at the port. Ideally you would refactor out modules/shared functions as being able to access variable from any part in the system will produce code that is harder to maintain
Dim YourobjName As YourClassName = Me.DataContext
Now you can use public methods and functions with YourobjName. Here YourClassName will be the class you want to access the public objects.