In Praise of Nested Classes
I love nested classes. You can do elegant thing wit them that otherwise require a ton of code - even if its generated. But the rest of the world seems confused by the syntax. Assuming a class named Budget, we could have Budget.List refer to a class (not an instance).
Public Class Budget
' Other Stuff
Public Class List
' Stuff
End Class
End Class
Unfortunately, the rest of the world is either confused by them, hasn't been introduced, or is following the Microsoft party line that they are uncool as expressed via FxCop. So to a large extent this post is a requiem. I have decided not to do what I'm describing here in my current architecture. At least today.
Since I think it is such a huge loss, I want to show you what nested classes can accomplish. Imagine an architecture tat contains these classes (with other meaningful stuff deleted):
Public MustInherit Class BizEntityBase(Of TEntity As EntityBase(Of TEntity))
End Class
Public Class Budget
Inherits BizEntityBase(Of Budget)
End Class
Public Class BudgetList
Inherits BizListBase(Of Budget)
Protected Sub New(ByVal list As IEnumerable(Of Budget))
MyBase.New(list)
End Sub
Public Function GetItem(ByVal id As Guid) As Budget
Dim q = From entity In Me Where entity.BudgetGuid = id
Return q.SingleOrDefault
End Function
Public Shared Function GetList() As BudgetList
Return GetListInternal(Of BudgetList)()
End Function
End Class
In this scenario, you have a copy for BudgetList for every single entity - probably hundreds adding many thousands of lines of code. Sure you can generate it, but it's better to reuse code than generate it. Now, use a nested class:
Public MustInherit Class BizEntityBase(Of TEntity As BizEntityBase(Of TEntity))
Public Class List
Inherits BizListBase(Of TEntity)
Protected Sub New(ByVal list As IEnumerable(Of TEntity))
MyBase.New(list)
End Sub
Public Function GetItem(ByVal id As Guid) As TEntity
Dim q = From entity In Me Where entity.PrimaryKeyValue = id
Return q.SingleOrDefault
End Function
Public Shared Function GetList() As EntityBase(Of TEntity).List
Return GetListInternal(Of EntityBase(Of TEntity).List)()
End Function
End Class
End Class
Public Class Budget
Inherits BizEntityBase(Of Budget)
End Class
As a result of this change, there is ONE location for the List functionality reused by all classes. There is no BudgetList class to be generated or handcrafted.It's not needed.
But external code must use Budget.List to access the class. I asked a smart structural architect know about this. He didn't even grok the question until I explained it. So for now, I'm skipping this approach at the same time I'm throwing it out there for other people to gnaw on.
Although I'm not completely skipping it. The entity list classes I'm writing derive and leverage base class code so are less lines than I'm showing above. But it's still hundreds of extra classes I see as existing only because as an industry we've yet to wrap our heads around this concept.