Interfaces and hungarian notation - vb.net

Please have a look at the following question: What's the naming convention for classes in the DataAccess Project?
JDK talks about using Namespaces to separate the Data Logic Layer and the Business Logic Layer and not to use Hungarian notation to name interfaces e.g. IPersonDAL for the data access layer. I have followed the recommendations of this answerer in the code below:
Imports com.app.BusinessLogicLayer.Interfaces
Imports com.app.DataLogicLayer.Interfaces
Namespace BusinessLogicLayer
Public Class Order
Implements com.app.BusinessLogicLayer.Interfaces.IOrder
Public Sub Insert()
Dim IOrder As com.app.DataLogicLayer.Interfaces.IOrder = New com.app.DataLogicLayer.Order
End Sub
End Class
End Namespace
Namespace DataLogicLayer
Public Class Order
Public Sub Insert()
End Sub
End Class
End Namespace
Namespace BusinessLogicLayer.Interfaces
Public Interface IOrder
End Interface
End Namespace
Namespace DataLogicLayer.Interfaces
Public Interface IOrder
End Interface
End Namespace
Classes in the business logic layer e.g. Order implement interfaces (IOrder from Business Logic Layer) and use interfaces (IOrder from Data Logic Layer) i.e. the presentation layer communicates with the Business Logic Layer and the Business Logic Layer communicates with the data logic layer with interfaces. Notice that because of this reason; interfaces have to be fully qualified with the namespace. For this reason; isn't it better to name interfaces using hungarian notation e.g. IPersonBLL and IPersonDAL or am I missing something?

Well, this is a subjective topic, but here goes...
Firstly, avoid abbreviations like DAL. Code Analysis yells about acronyms and abbreviations; you're supposed to write it out. In my experience it's wise advise. Opening up ancient code that's full of abbreviations causes a lot of unnecessary WTF moments (pun intended).
Even when spelling things out, when you have 50 classes sitting in your BusinessLogic folder like this:
Company.Product.BusinessLogic
PersonEntity
OrderEntity
MaterialEntity
EmployeeEntity
CustomerEntity
etc.
My gut tells me it's time to refactor. I feel it's better to move the Entity tag to the namespace, so you have this:
Company.Product.BusinessLogic.Entity
Person
Order
Material
Employee
Customer
etc.
Same things applies to interfaces.
This also makes it easier to refactor. If I want to start calling my Entities "BusinessObjects", I just have to rename the namespace, not the class names and file names.
It can be a pain to qualify your class names, but you normally only have to specify the parent namespace, not fully-qualify them. Resharper -> Cleanup Code does wonders here.
In summary, I would not add Hungarian notation to my interface/class name just to make references easier to deal with.
Update: Example
Data Access Layer:
Namespace Company.Product.DataAccess.Adapter
Public Class Product
End Class
End Namespace
Business Layer:
Imports Company.Product.DataAccess
Namespace Company.Product.BusinessLogic.Entity
Public Class Product
Dim adapter As New Adapter.Product()
End Class
End Namespace
User Interface (ideally your UI should only interact with the business layer, never with the data layer directly):
Imports Company.Product.BusinessLogic
Namespace Company.Product.UserInterface.Webpage
Public Class Product
Dim productEntity As New Entity.Product()
End Class
End Namespace

Notice that because of this reason; interfaces have to be fully qualified with the namespace. For this reason; isn't it better to name interfaces using hungarian notation e.g. IPersonBLL and IPersonDAL or am I missing something?
I see what you are saying, but I don't understand why fully-qualifying the names is bad or why it would be "better" to name the interfaces using "Hungarian" notation. (And I say this as a truly unrepentant fan of Simonyi's apps Hungarian.)
Remember that regardless of the names and locations of the classes/interfaces, the compiler is going to produce the same object code. The apparent nesting level is not going to "slow down" your code to any perceptible degree.
If it really bothers you to type out the names (and Intellisense is of no consolation), you can always use something like a namespace alias with a using directive. But I'd be careful with overusing these—I think it makes the code even harder to read.

Related

How to extend derived classes by defining class(es) that exposes the instance as a property

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.

Interfaces / Classes / Objects and Inheritance

I'm trying to rebuild some old QBASIC (yeah, you read that right) programs for use on more modern systems (because for some reason kids these days don't like DOS).
I understand the basic principles of classes and objects (I think) but I'm obviously missing something.
I have a number of instruments which are controlled using GPIB, using VISA COM libraries. I can make it work, but the code is very ugly :(
In order to use an instrument, I have the following in my Public Class Main:
Public ioMgr As Ivi.Visa.Interop.ResourceManager
Dim myInstrument As New Ivi.Visa.Interop.FormattedIO488
Dim myInstOpen As Boolean
Then, when I come to initializing the instrument (in the 'Initialize' button click sub), I use:
Try
myInstrument.IO = ioMgr.Open("GPIB0::17")
Catch exOpen As System.Runtime.InteropServices.COMException
myInstOpen = False
End Try
Pretty straightforward stuff; if the instrument can't be opened at address 17 on GPIB0, it throws an exception, which gets caught and sets the 'myInstOpen' flag to false.
Then, I can communicate with the instrument using commands from the Ivi.Visa.Interop.FormattedIO488 interface such as:
myInstrument.IO.ReadSTB()
result = myInstrument.ReadString()
myInstrument.WriteString("GPIB Command Here")
And all of it works.
What I want to do is, create a generic 'Instrument' class, that allows me access to all the functions from the Ivi.Visa.Interop.FormattedIO488 interface, and from the Ivi.Visa.Interop.ResourceManager interface, but also allows me to build my own class.
For instance:
Public Class GPIBInst
Implements Ivi.Visa.Interop.FormattedIO488
Public Address As Integer
Public Sub setAddress(ByVal Addr As Integer)
Address = Addr
End Sub
Public Function getAddress() As Integer
Return Address
End Function
Public Function readIO() As String
Dim Data As String = me.ReadString()
Dim Result As String = mid(Data,2,7)
Return Result
End Function
End Class
This would allow me to use the functions from the interface, but also customize the instruments for other useful things inside the program. For instance, the GPIBInst.Address needs to be used in other places, and the GPIBInst.readIO() can be used instead of just the generic ReadString() so that I can customize the output a little.
BUT when I try to do this, I can't inherit from the interface (because it's an interface) and I can't implement the interface because it says my class needs to implement every single function which the interface provides. I don't want all these functions, and also, I can't work out how to write them all into my class anyway (they have heaps of random stuff in them which I don't understand lol).
If anyone can see where I'm coming from and can offer some advice, I'd really appreciate it =)
An interface is supposed to represent a coherent set of functionality; implementing part of it but not all of it violates the intent of the concept. That being said, it is very common for APIs in object-oriented languages that wrap non-OO systems to just define one massive interface rather than breaking the functionality into logical sub-groups and defining an interface for each group. If that is your circumstance, and you want to implement the interface, you have no choice but to implement every method from the interface (although you can throw a NotImplementException for any method that you don't want to fully implement, as long as that will not prevent your class from functioning properly).

Dependency injection of local variable returned from method

I'm (somewhat) new to DI and am trying to understand how/why it's used in the codebase I am maintaining. I have found a series of classes that map data from stored procedure calls to domain objects. For example:
Public Sub New(domainFactory As IDomainFactory)
_domainFactory = domainFactory
End Sub
Protected Overrides Function MapFromRow(row As DataRow) As ISomeDomainObject
Dim domainObject = _domainFactory.CreateSomeDomainObject()
' Populate the object
domainObject.ID = CType(row("id"), Integer)
domainObject.StartDate = CType(row("date"), Date)
domainObject.Active = CType(row("enabled"), Boolean)
Return domainObject
End Function
The IDomainFactory is injected with Spring.Net. It's implementation simply has a series of methods that return new instances of the various domain objects. eg:
Public Function CreateSomeDomainObject() As ISomeDomainObject
Return New SomeDomainObject()
End Function
All of the above code strikes me as worse than useless. It's hard to follow and does nothing of value. Additionally, as far as I can tell it's a misuse of DI as it's not really intended for local variables. Furthermore, we don't need more than one implementation of the domain objects, we don't do any unit testing and if we did we still wouldn't mock the domain objects. As you can see from the above code, any changes to the domain object would be the result of changes to the SP, which would mean the MapFromRow method would have to be edited anyway.
That said, should I rip this nonsense out or is it doing something amazingly awesome and I'm missing it?
The idea behind dependency injection is to make a class (or another piece of code) independent on a specific implementation of an interface. The class outlined above does not know which class implements IDomainFactory. A concrete implementation is injected through its constructor and later used by the method MapFromRow. The domain factory returns an implementation of ISomeDomainObject which is also unknown.
This allows you supplement another implementation of these interfaces without having to change the class shown above. This is very practical for unit tests. Let's assume that you have an interface IDatabase that defines a method GetCustomerByID. It is difficult to test code that uses this method, since it depends on specific customer records in the database. Now you can inject a dummy database class that returns customers generated by code that does not access a physical database. Such a dummy class is often called a mock object.
See Dependency injection on Wikipedia.

OOP - Where to put the calls to the Data Access Layer?

I am implementing a Data Access Layer (DAL), which is basically a set of classes with (VB.NET) Shared functions to actually execute the database (CRUD) calls. I am trying to figure out the best place to place the calls to the DAL within the class hierarchy. Let me give an example.
Suppose I have a class Customer, with only standard ID, Name, Address1, etc. properties and maybe an overridden ToString function or so. I also have a DAL class with Shared methods, such as:
(pseudocode)
Namespace Dal
Public Class Customer
Public Shared Function Read(id As Integer) As Customer
Public Shared Function ReadList() As List(Of Customer)
Public Shared Sub Create(c As Customer)
'etc.
Now, I could call the Dal from the presentation layer like so:
Me.DataGridView1.Datasource = Dal.Customer.ReadList
However, is it not a good practice to have the presentation layer aware of the Dal at all? Should I instead put methods in the Customer object and call the Dal, like this?
Public Function ReadList() As List(Of Customer)
Return Dal.Customer.ReadList()
End Sub
Public Sub Create()
Dal.Customer.Create(Me)
End Sub
Would this be "cleaner" OOP? Or is it acceptable practice to let the presentation call the Dal, passing the business objects like my previous example:
Me.DataGridView1.Datasource = Dal.Customer.ReadList
Dim c As New Customer
c.Name = "Alpha Corporation"
c.Address1 = "123 Main Street"
Dal.Customer.Create(c)
Thanks for your feedback.
The less your application knows about your DAL the better. There are several ways to do this and I think you are on the right track. I think you might want to look into the factory pattern for this implementation as you will be able to hide the DAL implementation behind the factory and return entities and collections of entities from the factory.
I agree that data calls do not belong in a UI layer. Those are for presentation only.
I think they properly belong in a service layer. The service implementation uses model objects and the persistence layer to accomplish its goals. Whether that's an XML-based web service or local interface, the service is the object that maps to use cases and knows about units of work.
Either put the database calls into a separate persistence layer or embed them in the model objects for extra object-oriented purity.
The reason why'd you want to pull the CRUD operations into a separate layer is in case you ever want to change database systems. Well, that's why I did it. I wouldn't recommend doing this just to be good OOD. But here ya go...
Several sets of classes/interfaces
BusinessObject - Represents business type entities such as a Customer, has DataManager as a property.
DataManager - Maybe you can come up with a better name, but this thing provides Load() and Save() functions for the BusinessObjects
SearchList - Returns lists of things, your SQL queries go here. Also this should probably behave like a RecordSet with Next(), Eof(), and CurrentRecord type members
Constructor/Factory - See FactoryPattern. You've de-coupled your database operations from your business objects this thing re-couples them in a necessary way. Assigns an appropriate datamanager implementation to BusinessObject
Come up with whatever actual names you want, but let's talk about Customer again. Suppose you have an Oracle database. You might end up with these classes:
boCustomer that inherits from BusinessObject
oracleDMCustomer that inherits or implements DataManager
searchlistCustomer that inherits from searchlist that has exposed either through abstract methods or as an interface something like:
SearchAll() - which should return all customer
SearchByZip(String zip) which should return all customers with the given zipcode
oracleSearchlistCustomer - implements searchlistCustomer, would actually implement the SearchAll() and SearchByZip()
boFactory - static class that has a method that looks something like CreateObject(Type type)
searchlistFactory - static class that has a method that looks something like CreateSearchList(Type type);
I'll let you fill in some of the blanks, but I think the important stuff is there. Others may have different ideas that require less abstraction. I'd mock up several strategies before going with one.

MyClass in VB.Net

What is a realistic use for VB.Net's MyClass keyword?
I understand the technical usage of MyClass; I don't understand the practical usage of it in the real world.
Using MyClass only makes sense if you have any virtual (overridable) members. But it also means that you want to ignore the overridden implementations in sub classes. It appears to be self-contradicting.
I can think of some contrived examples, but they are simply bad design rather than practical usage.
MyClass, from a compiler's perspective, is a way to omit a callvirt instruction in favor of a call instruction. Essentially when you call a method with the virtual semantics (callvirt), you're indicating that you want to use the most derived variation. In cases where you wish to omit the derived variations you utilize MyClass (call). While you've stated you understand the basic concept, I figured it might help to describe it from a functional viewpoint, rather than an implicit understanding. It's functionally identical to MyBase with the caveat of scope being base type with MyBase, instead of the active type with MyClass.
Overriding virtual call semantics, at the current point in the hierarchy, is typically a bad design choice, the only times it is valid is when you must rely on a specific piece of functionality within your object's hierarchy, and can't rely on the inheritor to call your variation through a base invocation in their implementation. It could also rely on you as a designer deciding that it's the only alternative since you overrode the functionality further in the object hierarchy and you must ensure that in this corner case that this specific method, at the current level of the inheritance tree, must be called.
It's all about design, understanding the overall design and corner cases. There's likely a reason C♯ doesn't include such functionality since on those corner cases you could separate the method into a private variation the current level in the hierarchy invokes, and just refer to that private implementation when necessary. It's my personal view that utilizing the segmentation approach is the ideal means to an end since it's explicit about your design choice, and is easier to follow (and it's also the only valid means in languages without a functional equivalent to MyClass.)
Polymorphism
I'm sorry I don't have a clear code example here but you can follow the link below for that and I hate to copy the MSDN Library description but it's so good that it's really hard to rewrite it any clearer.
"MyClass provides a way to refer to the current class instance members without them being replaced by any derived class overrides. The MyClass keyword behaves like an object variable referring to the current instance of a class as originally implemented."
Also note that you can't use MyClass in a shared method.
A good example of implementing Polymorphism via MyClass is at http://www.devarticles.com/c/a/VB.Net/Implementing-Polymorphism-in-VB.Net/
I guess the only case I could see a use for it, would be if you want the base condition, and an inherited condition at the same time? I.E. where you want to be able to inherit a member, but you want the ability to access a value for that member that hasn't been changed by inheritance?
You need it if you want to call a chained constructor.
Public Sub New(ByVal accountKey As Integer)
MyClass.New(accountKey, Nothing)
End Sub
Public Sub New(ByVal accountKey As Integer, ByVal accountName As String)
MyClass.New(accountKey, accountName, Nothing)
End Sub
Public Sub New(ByVal accountKey As Integer, ByVal accountName As String, ByVal accountNumber As String)
m_AccountKey = accountKey
m_AccountName = accountName
m_AccountNumber = accountNumber
End Sub