Solution for Improve class design – there is a function that should not be callable
is Given Below:
Today, I thought to myself that I would quickly create a descriptive example of the access modifiers
Protected for someone, taken from real life.
The following example: A caretaker can spend a budget provided by the landlord himself without having to call for every little thing. For moderate repairs, however, he must call the landlord or the landlord’s son and ask for it. The son then knows what money he may spend. Big repairs can only be decided by the landlord (not the son).
I transferred that to source code.
I want to improve the class design, because I can still write
Tom.DecideMajorRepair (" ") in Form1.vb, which should not work and what I find unclean.
Public NotInheritable Class FormMain Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim Hans As New ClassVermieter ' Landlord Dim Tom As New ClassVermietersSohn ' Landlord's son 'easily accessible Dim MyBudget As UInt16 = Hans.Caretakers_budget_for_minor_repairs - 200US Dim Budget_received_1 As UInt16 = Hans.DecideModerateRepair("Unfortunately, the heating is broken!") ' Call son because father didn't answer the phone (or whatever). He can also decide that (protected). ' I still have to ask permission from one of them. Dim Budget_received_2 As UInt16 = Tom.DecideForHimselfModerateRepair("Unfortunately, the heating is broken!") ' Son cannot decide a major repair - only the landlord. Dim Budget_received_3 As UInt16 = Tom.DecideForHimselfLargeRepair("Unfortunately, the heating is broken!") Dim Budget_received_4 As UInt16 = Hans.DecideMajorRepair("Unfortunately, the heating is broken!") End Sub End Class
Public Class ClassVermieter ''' <summary> ''' per month ''' </summary> Public Property Caretakers_budget_for_minor_repairs As UInt16 = 500US '––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– Protected Property Permission_for_medium_repairs As UShort '––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– Private Permission_for_large_repairs As UInt16 'answers the phone call from the caretaker Public Function DecideModerateRepair(ByVal Message_from_the_caretaker As String) As UInt16 Permission_for_medium_repairs = 1000US Return Permission_for_medium_repairs End Function 'answers the phone call from the caretaker Public Function DecideMajorRepair(ByVal Message_from_the_caretaker As String) As UInt16 Permission_for_large_repairs = 5000US Return Permission_for_large_repairs End Function End Class
ClassVermietersSohn.vb (Landlord’s son)
Public Class ClassVermietersSohn : Inherits ClassVermieter Private ReadOnly zero As UInt16 = 0US 'answers the phone call from the caretaker 'He can decide for himself whether a moderate repair should be carried out. Public Function DecideForHimselfModerateRepair(ByVal Message_from_the_caretaker As String) As UInt16 Permission_for_medium_repairs = 1000US Return Permission_for_medium_repairs End Function 'answers the phone call from the caretaker Public Function DecideForHimselfLargeRepair(ByVal Message_from_the_caretaker As String) As UInt16 Return zero 'Well, that was nothing, because the son cannot spend (not see) the large amounts! End Function End Class
This code is kept elementarily. I am aware that money is not handled with Uint16. The first thing I wanted to do was build the structure.
The difficulty that kept me from solving it myself was that I didn’t know how to change the
Set without an error message.
In terms of the domain, I would not put the burden of knowing “whom” to ask on the caretaker. Ideally, the caretaker should have a single point of contact which can internally route the request and return true/false.
One design decision is how to parameterise the repair request.
This is most easily done by using an enum RepairTypes with a list of possible repair requests.
Then, I would have an interface “RepairApprover” with a method “boolean request(RepairType rt) throws NotSupportedException” – the exception would be used to “go up the chain”
Next, I would either have a LandlordAssistant class implement RepairApprover,
and a separate Landlord class also implementing RepairApprover.
Internally, the Landlord class would have a private field for LandlordAssistant so that it could reuse the code for minor and medium repairs.
I would then make a “ApprovalHierarchy” class with method “RepairApproval getMyManager()”
I would inject the LandlordAssistant as a “RepairApprover” instance into the Caretaker class constructor.
Internally, the LandlordAssistant.request method would try to respond to a small or medium request. If the request type is MAJOR, it would call ApprovalHierarchy.getMyManager(this).request(..) thus passing the request up the chain.
Hope that helps?