Cambios en cascada a futuras entradas en un horario -- vba camp codereview Relacionados El problema

Cascading Changes to Future Entries in a Schedule


6
vote

problema

Español

He estado trabajando en una aplicación de programación y tengo el nivel medio completado en este punto. No se cambia en unos pocos días, así que siento que está listo para su revisión. Solo tengo esta rutina que se siente sucia. Definitivamente está al borde del código de flecha, pero sin cortocircuito, no estoy seguro de cómo se puede mejorar más lejos.

MI Schedule3 WRAPT A COLECCIÓN DE ScheduleEntries y proporciona métodos para agregar entradas, eliminar entradas y cambios en cascada (así como una forma de escuchar los cambios en el colección subyacente). Cuando se llama CascadeChanges , la recopilación de entradas se busca registros sucios. Esos registros se encuentran en cascada a los registros correspondientes en ciclos futuros. Se deben cumplir una serie de condiciones para garantizar que los cambios se estén en cascada a las entradas futuras correctas. Actualmente, he sacrificado una cantidad de rendimiento para un código más limpio y más legible. ¿Cómo se puede mejorar este método?

  Public Sub CascadeChanges()     Dim innerEntries As SmartScheduleEntries     Set innerEntries = Me.Entries      '??? use group id to cascade changes?      Dim entry As SmartScheduleEntry     For Each entry In Me.Entries         If entry.IsDirty Then              Dim innerEntry As SmartScheduleEntry             For Each innerEntry In innerEntries                  If innerEntry.Store = entry.Store Then                      If (innerEntry.Cycle.Year = entry.Cycle.Year _                         And innerEntry.Cycle.Number > entry.Cycle.Number) _                     Or innerEntry.Cycle.Year > entry.Cycle.Year Then                          With innerEntry                             If .WeekDay = mOldWeekDay And .Week = mOldWeek And .Team = mOldTeam Then                                 .Team = entry.Team                                 .Week = entry.Week                                 .WeekDay = entry.WeekDay                             End If                         End With                     End If                  End If              Next innerEntry         End If     Next entry      RaiseEvent OnCascadeChanges End Sub   

Aquí están mis dos casos de prueba. (He estado usando Rubberduck a la unidad de la unidad todo esto).

  '@TestMethod Public Sub CascadeShouldUpdateFuture()     On Error GoTo TestFail  Arrange:     Dim mock As SmartSchedule     Set mock = Mocks.MockFullSchedule      Dim originalDay As VbDayOfWeek     originalDay = mock.Entries(1).WeekDay      Dim shouldBeChanged As New SmartScheduleEntries     Dim entry As SmartScheduleEntry     For Each entry In mock.Entries         If entry.WeekDay = originalDay And entry.Store = 6003 Then             shouldBeChanged.Add entry, entry.ID         End If     Next  Act:      mock.Entries(1).WeekDay = vbFriday ' make a change to first record     mock.CascadeChanges  Assert:     For Each entry In shouldBeChanged         Assert.AreEqual vbFriday, entry.WeekDay, "Cycle: " & entry.Cycle.ToString     Next  TestExit:     Exit Sub TestFail:     If Err.Number <> 0 Then         Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description     Else         Resume TestExit     End If End Sub  '@TestMethod Public Sub CascadeShouldNotUpdatePast()     On Error GoTo TestFail  Arrange:     Dim mock As SmartSchedule     Set mock = Mocks.MockFullSchedule      Dim originalDay As VbDayOfWeek     originalDay = mock.Entries(1).WeekDay      Dim shouldNotBeChanged As New SmartScheduleEntries     Dim entry As SmartScheduleEntry     For Each entry In mock.Entries         If entry.WeekDay <> originalDay And entry.Store <> 6003 Then             shouldNotBeChanged.Add entry, entry.ID         End If     Next  Act:      mock.Entries(1).WeekDay = vbFriday ' make a change to first record     mock.CascadeChanges  Assert:     For Each entry In shouldNotBeChanged         Assert.AreNotEqual vbFriday, entry.WeekDay, "Cycle: " & entry.Cycle.ToString & "; Store: " & entry.ToString     Next  TestExit:     Exit Sub TestFail:     If Err.Number <> 0 Then         Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description     Else         Resume TestExit     End If End Sub   

Para el contexto, a continuación encontrará las clases relevantes. Estoy feliz de recibir críticas sobre esto, pero estoy bastante feliz con ellos como lo son.

diagrama de UML

Horario:

  Option Explicit  Private WithEvents mEntries As SmartScheduleEntries  Public Event OnAddEntry(ByRef entry As SmartScheduleEntry) Public Event OnRemoveEntry(ByRef entry As SmartScheduleEntry) Public Event OnCascadeChanges()  Private mOldWeek As CycleWeek Private mOldWeekDay As VbDayOfWeek Private mOldTeam As String  Public Property Get Entries() As SmartScheduleEntries     Set Entries = mEntries End Property  Public Property Set Entries(ByVal value As SmartScheduleEntries)     Set mEntries = value End Property  Public Sub AddEntry(ByVal entry As SmartScheduleEntry)     mEntries.Add entry, entry.ID     RaiseEvent OnAddEntry(entry) End Sub  Public Sub RemoveEntry(ByVal entry As SmartScheduleEntry)     mEntries.Remove entry     RaiseEvent OnRemoveEntry(entry) End Sub  Public Sub Validate()     'todo: implement Validate()     RaiseNotImplementedError "Validate" End Sub  Public Sub CascadeChanges()     Dim innerEntries As SmartScheduleEntries     Set innerEntries = Me.Entries      '??? use group id to cascade changes?      Dim entry As SmartScheduleEntry     For Each entry In Me.Entries         If entry.IsDirty Then              Dim innerEntry As SmartScheduleEntry             For Each innerEntry In innerEntries                  If innerEntry.Store = entry.Store Then                      If (innerEntry.Cycle.Year = entry.Cycle.Year _                         And innerEntry.Cycle.Number > entry.Cycle.Number) _                     Or innerEntry.Cycle.Year > entry.Cycle.Year Then                          With innerEntry                             If .WeekDay = mOldWeekDay And .Week = mOldWeek And .Team = mOldTeam Then                                 .Team = entry.Team                                 .Week = entry.Week                                 .WeekDay = entry.WeekDay                             End If                         End With                     End If                  End If              Next innerEntry         End If     Next entry      RaiseEvent OnCascadeChanges End Sub  Public Sub CleanEntries()     Dim entry As SmartScheduleEntry     For Each entry In mEntries         entry.IsDirty = False     Next End Sub  Private Sub Class_Initialize()     Set mEntries = New SmartScheduleEntries End Sub  Private Sub mEntries_Add(ByRef entry As SmartScheduleEntry)     ' ReRaises event     RaiseEvent OnAddEntry(entry) End Sub  Private Sub mEntries_ItemChanged(ByRef outWeek As CycleWeek, ByRef outWeekDay As VbDayOfWeek, ByRef outTeam As String)     mOldWeekDay = outWeekDay     mOldWeek = outWeek     mOldTeam = outTeam End Sub  Private Sub mEntries_Remove(ByRef entry As SmartScheduleEntry)     ' ReRaises Event     RaiseEvent OnRemoveEntry(entry) End Sub  Private Sub RaiseNotImplementedError(ByVal procName As String)     Err.Raise vbObjectError + 1, TypeName(Me) & "." & procName, "Not implemented yet." End Sub   

entrada:

  Option Explicit  Public Enum ScheduleEntryError     ReadOnlyPropertyError = vbObjectError + 3333 End Enum  Public Enum CycleWeek     weekOne = 1     WeekTwo End Enum  Private Type TScheduleEntry     ID As Long     GroupID As Long     Cycle As Cycle     Team As String     Store As Integer     WeekDay As VbDayOfWeek     Week As CycleWeek     IsDirty As Boolean End Type  Private this As TScheduleEntry  Public Event OnWeekDayChange(ByRef outDay As VbDayOfWeek) Public Event OnWeekChange(ByRef outWeek As CycleWeek) Public Event OnTeamChange(ByRef outTeam As String)  Public Property Get ID() As Long     ID = this.ID End Property  Public Property Let ID(ByVal value As Long)     If this.ID = 0 Then         this.ID = value     Else         RaiseReadOnlyError "ID"     End If End Property  Public Property Get GroupID() As Long     GroupID = this.GroupID End Property  Public Property Let GroupID(ByVal value As Long)     If this.GroupID = 0 Then         this.GroupID = value     Else         RaiseReadOnlyError "GroupID"     End If End Property  Public Property Get IsDirty() As Boolean     IsDirty = this.IsDirty End Property  Public Property Let IsDirty(ByVal value As Boolean)     this.IsDirty = value End Property  Public Property Get Team() As String     Team = this.Team End Property  Public Property Let Team(ByVal value As String)     Dim old As String     old = this.Team      this.Team = value     this.IsDirty = True      RaiseEvent OnTeamChange(old) End Property  Public Property Get Store() As Integer     Store = this.Store End Property  Public Property Let Store(ByVal value As Integer)     this.Store = value     this.IsDirty = True End Property  Public Property Get Cycle() As Cycle     Set Cycle = this.Cycle End Property  Public Property Set Cycle(ByVal value As Cycle)     Set this.Cycle = value     this.IsDirty = True End Property  Public Property Get Week() As CycleWeek     Week = this.Week End Property  Public Property Let Week(ByVal value As CycleWeek)     Dim old As CycleWeek     old = this.Week      this.Week = value     this.IsDirty = True      RaiseEvent OnWeekChange(old) End Property  Public Property Get WeekDay() As VbDayOfWeek     WeekDay = this.WeekDay End Property  Public Property Let WeekDay(ByVal value As VbDayOfWeek)      Dim old As VbDayOfWeek     old = this.WeekDay      this.WeekDay = value     this.IsDirty = True      RaiseEvent OnWeekDayChange(old) End Property  'read-only property Public Property Get SetDate() As Date     Dim result As Date      ' vbMonday == 2, and our week starts on Monday.     '   If DayOfWeek == vbMonday, it is the startdate, we should add zero days.     '   In other words, Add (2 - 2) to startdate if it's Monday.      If this.Week = weekOne Then         result = DateAdd("d", this.WeekDay - 2, this.Cycle.StartDate)     Else         result = DateAdd("d", this.WeekDay - 2 + 7, this.Cycle.StartDate)     End If      SetDate = result End Property  Public Function ToString() As String     ToString = this.Cycle.ToString & "," & this.Team & "," & this.Store & "," & this.Week & "," & this.WeekDay & "," & this.IsDirty End Function  Private Sub RaiseReadOnlyError(ByVal procName As String)     Err.Raise ScheduleEntryError.ReadOnlyPropertyError, TypeName(Me) & "." & procName, "Property Is ReadOnly." End Sub   

entradas Recopilación:

  id0  

ciclo:

  id1  
Original en ingles

I've been working on a scheduling application and I have the middle tier completed at this point. It's not changed in a few days, so I feel it's ready for review. I have just this one routine that feels dirty. It's definitely verging on arrow code, but without short-circuiting, I'm not sure how it can be improved any farther.

My Schedule class wraps a collection of ScheduleEntries and provides methods to add entries, remove entries, and cascade changes (as well as a way to listen for changes to the underlying collection). When CascadeChanges is called, the collection of entries is searched for dirty records. Those records are then cascaded to the corresponding records in future Cycles. A number of conditions must be met in order to ensure changes are being cascaded to the correct future entries. Currently, I have sacrificed an amount of performance for cleaner, more readable code. How can this method be improved?

Public Sub CascadeChanges()     Dim innerEntries As SmartScheduleEntries     Set innerEntries = Me.Entries      '??? use group id to cascade changes?      Dim entry As SmartScheduleEntry     For Each entry In Me.Entries         If entry.IsDirty Then              Dim innerEntry As SmartScheduleEntry             For Each innerEntry In innerEntries                  If innerEntry.Store = entry.Store Then                      If (innerEntry.Cycle.Year = entry.Cycle.Year _                         And innerEntry.Cycle.Number > entry.Cycle.Number) _                     Or innerEntry.Cycle.Year > entry.Cycle.Year Then                          With innerEntry                             If .WeekDay = mOldWeekDay And .Week = mOldWeek And .Team = mOldTeam Then                                 .Team = entry.Team                                 .Week = entry.Week                                 .WeekDay = entry.WeekDay                             End If                         End With                     End If                  End If              Next innerEntry         End If     Next entry      RaiseEvent OnCascadeChanges End Sub 

Here are my two test cases. (I've been using Rubberduck to unit test all of this.)

'@TestMethod Public Sub CascadeShouldUpdateFuture()     On Error GoTo TestFail  Arrange:     Dim mock As SmartSchedule     Set mock = Mocks.MockFullSchedule      Dim originalDay As VbDayOfWeek     originalDay = mock.Entries(1).WeekDay      Dim shouldBeChanged As New SmartScheduleEntries     Dim entry As SmartScheduleEntry     For Each entry In mock.Entries         If entry.WeekDay = originalDay And entry.Store = 6003 Then             shouldBeChanged.Add entry, entry.ID         End If     Next  Act:      mock.Entries(1).WeekDay = vbFriday ' make a change to first record     mock.CascadeChanges  Assert:     For Each entry In shouldBeChanged         Assert.AreEqual vbFriday, entry.WeekDay, "Cycle: " & entry.Cycle.ToString     Next  TestExit:     Exit Sub TestFail:     If Err.Number <> 0 Then         Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description     Else         Resume TestExit     End If End Sub  '@TestMethod Public Sub CascadeShouldNotUpdatePast()     On Error GoTo TestFail  Arrange:     Dim mock As SmartSchedule     Set mock = Mocks.MockFullSchedule      Dim originalDay As VbDayOfWeek     originalDay = mock.Entries(1).WeekDay      Dim shouldNotBeChanged As New SmartScheduleEntries     Dim entry As SmartScheduleEntry     For Each entry In mock.Entries         If entry.WeekDay <> originalDay And entry.Store <> 6003 Then             shouldNotBeChanged.Add entry, entry.ID         End If     Next  Act:      mock.Entries(1).WeekDay = vbFriday ' make a change to first record     mock.CascadeChanges  Assert:     For Each entry In shouldNotBeChanged         Assert.AreNotEqual vbFriday, entry.WeekDay, "Cycle: " & entry.Cycle.ToString & "; Store: " & entry.ToString     Next  TestExit:     Exit Sub TestFail:     If Err.Number <> 0 Then         Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description     Else         Resume TestExit     End If End Sub 

For context, below you will find the relevant classes. I'm happy to receive criticism on these, but I'm pretty happy with them as they are.

UML diagram

Schedule:

Option Explicit  Private WithEvents mEntries As SmartScheduleEntries  Public Event OnAddEntry(ByRef entry As SmartScheduleEntry) Public Event OnRemoveEntry(ByRef entry As SmartScheduleEntry) Public Event OnCascadeChanges()  Private mOldWeek As CycleWeek Private mOldWeekDay As VbDayOfWeek Private mOldTeam As String  Public Property Get Entries() As SmartScheduleEntries     Set Entries = mEntries End Property  Public Property Set Entries(ByVal value As SmartScheduleEntries)     Set mEntries = value End Property  Public Sub AddEntry(ByVal entry As SmartScheduleEntry)     mEntries.Add entry, entry.ID     RaiseEvent OnAddEntry(entry) End Sub  Public Sub RemoveEntry(ByVal entry As SmartScheduleEntry)     mEntries.Remove entry     RaiseEvent OnRemoveEntry(entry) End Sub  Public Sub Validate()     'todo: implement Validate()     RaiseNotImplementedError "Validate" End Sub  Public Sub CascadeChanges()     Dim innerEntries As SmartScheduleEntries     Set innerEntries = Me.Entries      '??? use group id to cascade changes?      Dim entry As SmartScheduleEntry     For Each entry In Me.Entries         If entry.IsDirty Then              Dim innerEntry As SmartScheduleEntry             For Each innerEntry In innerEntries                  If innerEntry.Store = entry.Store Then                      If (innerEntry.Cycle.Year = entry.Cycle.Year _                         And innerEntry.Cycle.Number > entry.Cycle.Number) _                     Or innerEntry.Cycle.Year > entry.Cycle.Year Then                          With innerEntry                             If .WeekDay = mOldWeekDay And .Week = mOldWeek And .Team = mOldTeam Then                                 .Team = entry.Team                                 .Week = entry.Week                                 .WeekDay = entry.WeekDay                             End If                         End With                     End If                  End If              Next innerEntry         End If     Next entry      RaiseEvent OnCascadeChanges End Sub  Public Sub CleanEntries()     Dim entry As SmartScheduleEntry     For Each entry In mEntries         entry.IsDirty = False     Next End Sub  Private Sub Class_Initialize()     Set mEntries = New SmartScheduleEntries End Sub  Private Sub mEntries_Add(ByRef entry As SmartScheduleEntry)     ' ReRaises event     RaiseEvent OnAddEntry(entry) End Sub  Private Sub mEntries_ItemChanged(ByRef outWeek As CycleWeek, ByRef outWeekDay As VbDayOfWeek, ByRef outTeam As String)     mOldWeekDay = outWeekDay     mOldWeek = outWeek     mOldTeam = outTeam End Sub  Private Sub mEntries_Remove(ByRef entry As SmartScheduleEntry)     ' ReRaises Event     RaiseEvent OnRemoveEntry(entry) End Sub  Private Sub RaiseNotImplementedError(ByVal procName As String)     Err.Raise vbObjectError + 1, TypeName(Me) & "." & procName, "Not implemented yet." End Sub 

Entry:

Option Explicit  Public Enum ScheduleEntryError     ReadOnlyPropertyError = vbObjectError + 3333 End Enum  Public Enum CycleWeek     weekOne = 1     WeekTwo End Enum  Private Type TScheduleEntry     ID As Long     GroupID As Long     Cycle As Cycle     Team As String     Store As Integer     WeekDay As VbDayOfWeek     Week As CycleWeek     IsDirty As Boolean End Type  Private this As TScheduleEntry  Public Event OnWeekDayChange(ByRef outDay As VbDayOfWeek) Public Event OnWeekChange(ByRef outWeek As CycleWeek) Public Event OnTeamChange(ByRef outTeam As String)  Public Property Get ID() As Long     ID = this.ID End Property  Public Property Let ID(ByVal value As Long)     If this.ID = 0 Then         this.ID = value     Else         RaiseReadOnlyError "ID"     End If End Property  Public Property Get GroupID() As Long     GroupID = this.GroupID End Property  Public Property Let GroupID(ByVal value As Long)     If this.GroupID = 0 Then         this.GroupID = value     Else         RaiseReadOnlyError "GroupID"     End If End Property  Public Property Get IsDirty() As Boolean     IsDirty = this.IsDirty End Property  Public Property Let IsDirty(ByVal value As Boolean)     this.IsDirty = value End Property  Public Property Get Team() As String     Team = this.Team End Property  Public Property Let Team(ByVal value As String)     Dim old As String     old = this.Team      this.Team = value     this.IsDirty = True      RaiseEvent OnTeamChange(old) End Property  Public Property Get Store() As Integer     Store = this.Store End Property  Public Property Let Store(ByVal value As Integer)     this.Store = value     this.IsDirty = True End Property  Public Property Get Cycle() As Cycle     Set Cycle = this.Cycle End Property  Public Property Set Cycle(ByVal value As Cycle)     Set this.Cycle = value     this.IsDirty = True End Property  Public Property Get Week() As CycleWeek     Week = this.Week End Property  Public Property Let Week(ByVal value As CycleWeek)     Dim old As CycleWeek     old = this.Week      this.Week = value     this.IsDirty = True      RaiseEvent OnWeekChange(old) End Property  Public Property Get WeekDay() As VbDayOfWeek     WeekDay = this.WeekDay End Property  Public Property Let WeekDay(ByVal value As VbDayOfWeek)      Dim old As VbDayOfWeek     old = this.WeekDay      this.WeekDay = value     this.IsDirty = True      RaiseEvent OnWeekDayChange(old) End Property  'read-only property Public Property Get SetDate() As Date     Dim result As Date      ' vbMonday == 2, and our week starts on Monday.     '   If DayOfWeek == vbMonday, it is the startdate, we should add zero days.     '   In other words, Add (2 - 2) to startdate if it's Monday.      If this.Week = weekOne Then         result = DateAdd("d", this.WeekDay - 2, this.Cycle.StartDate)     Else         result = DateAdd("d", this.WeekDay - 2 + 7, this.Cycle.StartDate)     End If      SetDate = result End Property  Public Function ToString() As String     ToString = this.Cycle.ToString & "," & this.Team & "," & this.Store & "," & this.Week & "," & this.WeekDay & "," & this.IsDirty End Function  Private Sub RaiseReadOnlyError(ByVal procName As String)     Err.Raise ScheduleEntryError.ReadOnlyPropertyError, TypeName(Me) & "." & procName, "Property Is ReadOnly." End Sub 

Entries Collection:

VERSION 1.0 CLASS BEGIN   MultiUse = -1  'True END Attribute VB_Name = "SmartScheduleEntries" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit  Private mCollection As Collection Private WithEvents mEntryListener As SmartScheduleEntry Attribute mEntryListener.VB_VarHelpID = -1  Public Event Added(ByRef entry As SmartScheduleEntry) Public Event Removed(ByRef entry As SmartScheduleEntry) Public Event ItemChanged(ByRef outWeek As CycleWeek, ByRef outWeekDay As VbDayOfWeek, ByRef outTeam As String)  Public Function Add(ByRef entry As SmartScheduleEntry, ByVal Key As Long)     mCollection.Add entry, CStr(Key)     RaiseEvent Added(entry) End Function  Public Function Remove(ByVal entry As SmartScheduleEntry)      mCollection.Remove IndexOf(entry)      RaiseEvent Removed(entry) End Function  Public Function Item(ByVal index As Variant) As SmartScheduleEntry Attribute Item.VB_UserMemId = 0      Set mEntryListener = mCollection(index)     Set Item = mEntryListener  End Function  Public Function Count() As Long     Count = mCollection.Count End Function  ' returns index of item if found, returns 0 if not found Public Function IndexOf(ByVal entry As SmartScheduleEntry) As Long     Dim i As Long     For i = 1 To mCollection.Count         If mCollection(i).ID = entry.ID Then             IndexOf = i             Exit Function         End If     Next End Function  Public Function NewEnum() As IUnknown Attribute NewEnum.VB_UserMemId = -4     Set NewEnum = mCollection.[_NewEnum] End Function  Private Sub Class_Initialize()     Set mCollection = New Collection End Sub  Private Sub Class_Terminate()     Set mCollection = Nothing End Sub  Private Sub mEntryListener_OnTeamChange(ByRef outTeam As String)     RaiseEvent ItemChanged(mEntryListener.Week, mEntryListener.WeekDay, outTeam) End Sub  Private Sub mEntryListener_OnWeekChange(ByRef outWeek As CycleWeek)     RaiseEvent ItemChanged(outWeek, mEntryListener.WeekDay, mEntryListener.Team) End Sub  Private Sub mEntryListener_OnWeekDayChange(ByRef outDay As VbDayOfWeek)     RaiseEvent ItemChanged(mEntryListener.Week, outDay, mEntryListener.Team) End Sub 

Cycle:

Option Explicit  Private Type TCycle     StartDate As Date     EndDate As Date     Year As Integer     Number As Integer End Type  Private this As TCycle  Public Property Get Year() As Integer     Year = this.Year End Property  Public Property Let Year(ByVal value As Integer)     this.Year = value End Property  Public Property Get Number() As Integer     Number = this.Number End Property  Public Property Let Number(ByVal value As Integer)     this.Number = value End Property  Public Property Get StartDate() As Date     StartDate = DateValue(this.StartDate) End Property  Public Property Let StartDate(ByVal value As Date)     this.StartDate = value End Property  Public Property Get EndDate() As Date     EndDate = DateValue(this.EndDate) End Property  Public Property Let EndDate(ByVal value As Date)     this.EndDate = value End Property  Public Function ToString() As String     ToString = this.Year & "-P" & Format(this.Number, "00") End Function  Public Sub SetFromString(ByVal value As String)     Dim arr As Variant      arr = Split(value, "-P", 2)     Me.Year = arr(0)     Me.Number = arr(1) End Sub 
  

Lista de respuestas

3
 
vote
vote
La mejor respuesta
 

Arrow Antipattern

Sí, su código de flecha está sucio, se puede dividir en otros métodos. Quizás solo se usan en un método ahora, pero a medida que su código se expande, le resultará conveniente que estos métodos ya estén definidos. Encuentro mantener todos los métodos para que se ayuden a una o dos estructuras de control. Por favor, los mejores nombres deben usarse de lo que utilicé, ya que no entiendo completamente su producto.

  Public Sub CascadeChanges()      Dim entries As SmartScheduleEntries     Set entries = Me.Entries      Dim entry As SmartScheduleEntry     For Each entry in entries          If entry.IsDirty Then CascadeEntry entry, entries     Next entry      RaiseEvent OnCascadeChanges  End Sub Private Sub CascadeEntry(ByVal inputEntry As SmartScheduleEntry, _         ByVal entries As SmartScheduleEntries)      Dim entry As SmartScheduleEntry     For Each entry In entries         If OughtCascade(inputEntry, entry) And IsOutDated(entry) Then              DoCascade inputEntry, entry         End If     Next entry   End Sub Private Function IsOutDated(ByVal entry As SmartScheduleEntry) As Boolean     IsOutDated = (entry.WeekDay = mOldWeekDay And _                   entry.Week = mOldWeek And _                   entry.Team = mOldTeam) End Function   

Es posible que desee abstraer varias comparaciones de OughtCascade , pero sí sé cuáles son lo suficientemente relevantes como para abstraer. Todas las comparaciones son solo propiedades simples, por lo que la falta de evaluación de cortocircuito tiene un costo marginal. Mirando a su clase de programador, no todos estos métodos pertenecen a esa clase. Los siguientes dos podrían ser trasladados a su clase SmartScheduleEntry .

  Private Function OughtCascade(ByVal entryFrom SmartScheduleEntry, _         ByVal entryTo SmartScheduleEntry) As Boolean     OughtCascade = (entryFrom.Store = entryTo.Store) And _                    ((entryFrom.Cycle.Year = entryTo.Cycle.Year) And _                    (entryFrom.Cycle.Number < entryTo.Cycle.Number) Or _                    (entryFrom.Cycle.Year < entryTo.Cycle.Year)) End Function  Public Sub DoCascade(ByRef entryFrom As SmartScheduleEntry, _         ByRef entryTo As SmartScheduleEntry      With entryTo              .Team = entryFrom.Team             .Week = entryFrom.Week             .WeekDay = entryFrom.WeekDay      End With  End Sub   

IsDirty está sucio

Mirando más lejos en su código. Me estoy volviendo sospechoso del miembro 9988776665544335 . Creo que la propiedad debe evaluar si la entrada está sucia o no y no leer de un miembro. Parece que está causando el código de la placa de la caldera en las propiedades de Permiso de otros miembros.

  Public Property Let WeekDay(ByVal value As VbDayOfWeek)      Dim old As VbDayOfWeek     old = this.WeekDay      this.WeekDay = value     this.IsDirty = True      RaiseEvent OnWeekDayChange(old) End Property   

El problema es Get IsDirty depende del Código de Let WeekDay y otras propiedades. Get IsDirty debe ser independiente sobre cualquier método que no haga referencia específicamente. AISLAMIENTO OughtCascade0 puede requerir completamente rediseñar su estructura. Ver como OughtCascade16655443311 es sinónimo de hasmutated , considere hacer su OughtCascade2 inmutable.

 

Arrow AntiPattern

Yes your arrow code is dirty it can be broken down into other methods. They maybe only used in one method now but as your code expands you will find it convenient that these methods are already defined. I find keeping every method to one or two control structures helps. Please better names should be used than what I used as I don't fully understand your product.

Public Sub CascadeChanges()      Dim entries As SmartScheduleEntries     Set entries = Me.Entries      Dim entry As SmartScheduleEntry     For Each entry in entries          If entry.IsDirty Then CascadeEntry entry, entries     Next entry      RaiseEvent OnCascadeChanges  End Sub Private Sub CascadeEntry(ByVal inputEntry As SmartScheduleEntry, _         ByVal entries As SmartScheduleEntries)      Dim entry As SmartScheduleEntry     For Each entry In entries         If OughtCascade(inputEntry, entry) And IsOutDated(entry) Then              DoCascade inputEntry, entry         End If     Next entry   End Sub Private Function IsOutDated(ByVal entry As SmartScheduleEntry) As Boolean     IsOutDated = (entry.WeekDay = mOldWeekDay And _                   entry.Week = mOldWeek And _                   entry.Team = mOldTeam) End Function 

You might want to abstract various comparisons of OughtCascade out but I do know which are relevant enough to abstract. All of the comparisons are just simple properties, so the lack of short circuit evaluation has marginal cost. Looking back into your Scheduler class, not all of these methods belong in that class. The following two could be ported to your SmartScheduleEntry class.

Private Function OughtCascade(ByVal entryFrom SmartScheduleEntry, _         ByVal entryTo SmartScheduleEntry) As Boolean     OughtCascade = (entryFrom.Store = entryTo.Store) And _                    ((entryFrom.Cycle.Year = entryTo.Cycle.Year) And _                    (entryFrom.Cycle.Number < entryTo.Cycle.Number) Or _                    (entryFrom.Cycle.Year < entryTo.Cycle.Year)) End Function  Public Sub DoCascade(ByRef entryFrom As SmartScheduleEntry, _         ByRef entryTo As SmartScheduleEntry      With entryTo              .Team = entryFrom.Team             .Week = entryFrom.Week             .WeekDay = entryFrom.WeekDay      End With  End Sub 

IsDirty is Dirty

Looking further at your code I am becoming suspicious of the IsDirty member. I believe the property should evaluate whether the entry is dirty or not and not read from a member. It appears to be causing boiler plate code in the Let properties of other members.

Public Property Let WeekDay(ByVal value As VbDayOfWeek)      Dim old As VbDayOfWeek     old = this.WeekDay      this.WeekDay = value     this.IsDirty = True      RaiseEvent OnWeekDayChange(old) End Property 

The issue is Get IsDirty is dependent on the code of Let WeekDay and other properties. Get IsDirty should be independent on any methods it does not specifically reference. Isolating IsDirty may require completely redesigning your structure. Seeing as IsDirty seems to be synonymous with HasMutated, consider making your SmartScheduleEntry class immutable.

 
 
 
 
3
 
vote

Pensé que sabías mejor que usar los números mágicos

  OughtCascade3  

¿Qué es tan especial acerca de la tienda OughtCascade4 ?


¿Qué tipo de error es este?

  OughtCascade5  

¿Un error de número mágico?


Encontré esto útil para explicar la lógica aquí que no habría tenido sentido lo contrario.

  OughtCascade6  

El código se ve bonito, para VB de todos modos.

 

I thought you knew better than to use Magic numbers

For Each entry In mock.Entries     If entry.WeekDay = originalDay And entry.Store = 6003 Then         shouldBeChanged.Add entry, entry.ID     End If Next 

what is so special about store 6003?


What kind of Error is this?

Public Enum ScheduleEntryError     ReadOnlyPropertyError = vbObjectError + 3333 End Enum 

A Magic Number Error?


I did find this useful to explain the logic here that wouldn't have made sense otherwise.

'read-only property Public Property Get SetDate() As Date     Dim result As Date      ' vbMonday == 2, and our week starts on Monday.     '   If DayOfWeek == vbMonday, it is the startdate, we should add zero days.     '   In other words, Add (2 - 2) to startdate if it's Monday.      If this.Week = weekOne Then         result = DateAdd("d", this.WeekDay - 2, this.Cycle.StartDate)     Else         result = DateAdd("d", this.WeekDay - 2 + 7, this.Cycle.StartDate)     End If      SetDate = result End Property 

Code looks Pretty, for VB anyway.

 
 
 
 

Relacionados problema

6  Crear tabla que enumera la visibilidad de la hoja de trabajo  ( Create table that lists worksheet visibility ) 
Siguiendo mi pregunta anterior crear Una tabla que enumera las macros en un libro de trabajo o hoja de trabajo Aquí está mi Sub para determinar la visibilid...

10  Imitación básica de C # enumerable en VBA - o cualquier otra clase estática  ( Basic imitation of c enumerable in vba or any other static class ) 
Desde la implementación de clases estáticas en VBA en realidad parece posible Se me ocurrió una idea para tratar de imitar C # ' 9988776655544330 clase ...

2  Búsqueda de pruebas de abstracción y unidad en mesa Excel  ( Abstracting and unit testing lookups in excel table ) 
Fondo Tengo una solución de VBA que utilizo para ingerir informes de texto de inversión y reformatearlos para su análisis en Excel. Funciona, pero las macro...

2  Importando datos en Excel  ( Importing data into excel ) 
¿Existe una forma más fácil de importar datos en una matriz de Excel u otra estructura de datos? He intentado investigar colecciones, pero he encontrado la D...

6  Fijación de archivos de reclamación médica a través del archivo de texto Lea / escribe  ( Fixing medical claim files through text file read write ) 
Con Gracias a @ Mat'Smug y @comintern por su aliento, aquí hay un programa que escribí para ayudar a mi equipo a reparar archivos de reclamación médica. El ...

5  Copiando datos de libros cerrados  ( Copying data from closed workbooks ) 
Soy un pasante en una empresa industrial en Brasil y sucede que estoy usando mucho en Excel. Acabo de empezar a jugar con VBA hace un par de días, ¡y me divie...

7  Recuperando datos de archivos en la carpeta  ( Retrieving data from files in the folder ) 
Estoy a usar el código VBA para simplemente recuperar ciertos datos de todos los archivos de Excel en cierta carpeta y pegarlo en la hoja de cálculo de trabaj...

6  Juego de serpientes - Dentro de la hoja de trabajo - Celdas como píxeles  ( Snake game within worksheet cells as pixels ) 
Desde mi intento bastante mediocre de hacer un juego de invasores del espacio, me topé con un caché de juegos de Visual Basic para solicitar juegos escritos p...

48  Lista <T> Implementación para VB6 / VBA  ( Listt implementation for vb6 vba ) 
Recientemente, decidí que el 998877665555544330 no fue suficiente para mis necesidades, así que decidí implementar algo como C # 's List<T> . Aquí está la ...

3  Comparando células de dos hojas de trabajo  ( Comparing cells of two worksheets ) 
Con el siguiente código, trato de comparar el contenido de dos hojas de trabajo. La primera columna contiene una clave que es única y las siguientes columnas ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos