OOP Design Smell?
Summary
I'm actually writing an object-oriented class library for dealing with the Active Directory in Visual Basic .NET 2005.The library allows to manage Organizational Units, Groups and Users.
I have strived to generalize as much as I could making my code look like (simplified):
Public Interface IDirectoryEntityBase
ReadOnly Property DistinguishedName As String
ReadOnly Property Domain As String
Property Name As String
ReadOnly Property Schema As String
End Interface
Public Interface IDirectoryEntity
Inherits IDirectoryEntryBase
Property Login As String
End Interface
Public MustInherit Class DirectoryEntity
Implements IDirectoryEntity
Private _distinguishedName As String
Private _domain As String
Private _name As String
Private _schema As String
Public Sub New(ByVal pName As String)
Name = pName
End Sub
Public ReadOnly Property DistinguishedName As String Implements IDirectoryEntryBase.Name
Get
Return _name
End Get
End Property
Public ReadOnly Property Domain As String Implements IDirectoryEntryBase.Domain
Get
Return _domain
End Get
End Property
Public Property Name As String Implements IDirectoryEntryBase.Name
Get
Return _name
End Get
Set(ByVal value As String)
If (String.IsNullOrEmpty(value)) Then Return
_name = value.Trim()
End Set
End Property
Public ReadOnly Property Schema As String Implements IDirectoryEntryBase.Schema
Get
Throw New NotImplementedException()
End Get
End Property
End Class
Public Interface IOrganizationalUnit
Inherits IDirectoryEntity
ReadOnly Property Children As ICollection(Of IDirectoryEntityBase)
End Interface
Public Class OrganizationalUnit
Inherits DirectoryEntity
Implements IOrganizationalUnit
Private _children As ICollection(Of IDirectoryEntityBase)
Public Sub New(ByVal pName As String开发者_JS百科)
MyBase.New(pName)
_children = new List(Of IDirectoryEntity)()
End Sub
Public ReadOnly Property Children As ICollection(Of IDirectoryEntityBase) Implements IOrganizationalUnit.Children
Get
Return _children
End Get
End Property
End Class
Public Interface IGroup
Inherits IDirectoryEntity
ReadOnly Property Members As ICollection(Of IDirectoryEntity)
End Interface
Public Class Group
Inherits DirectoryEntity
Implements IGroup
Private _members As ICollection(Of IDirectoryEntity)
Public Sub New(ByVal pName As String)
MyBase.New(pName)
_members = New List(Of IDirectoryEntity)()
End Sub
Public ReadOnly Property Members As ICollection(Of IDirectoryEntity) Implements IGroup.Members
Get
Return _members
End Get
End Property
End Class
Now, when I have added my instances of whichever type into my Domain.Entries
through my Domain.Add Method
, I may call the Domain.AcceptChanges Method
so that any instances are processed.
My Domain.Entries
property is a ICollection(Of DirectoryEntryBase)
.
Question
It is when I call myDomain.AcceptChanges Method
that I find myself handcuffed by having to know what schema or what type I'm working with, since I need to access the OrganizationalUnit.Children
or the Group.Members
collections depending on their type.
Public Class Domain
Public Sub AcceptChanges()
For Each e As DirectoryEntry In Entries
'How may I find out what collection to work with here?'
Next
End Sub
End Class
I have thought about generalizing this collection, but then again, the vocabulary changes from an objet to another. As for an OU, we might speak about Children, when for a Group, we will say Members, etc. In fact, these do not refer to the same reality, so I would generalize this collection for a bad reason, I guess.
Any thoughts?
Thanks!
I think you should genralize the collection as, say, a 'BaseList
' which would house the common properties for both OrganizationalUnit.Children and Group.Members.
Then the Children and Member classes could extend that base class and add other custom functionality that needs to occur when you accept changes.
So in summary:
public class BaseList
{
public virtual void Persist(...);
// Common stuff
}
public class Children
{
public override void Persist(...)
{
// do custom stuff
}
}
public class Members
{
public override void Persist(...)
{
// do custom stuff
}
}
Then you can loop through a collection of 'BaseList
' and call each individual persist method.
精彩评论