Object-oriented design implementation of an ElevatorObject Orientated PHP, what's wrong with this implementation of OOPHP and how might it be improved?Cinema schedulingBowling scorecard appPoker Hand classifer part 3: Deck Object and 7 Card HandLeetcode 317: Shortest distance from all buildingsPHP subset of 2 arrays containing objects - compared only by 1 attributeCreating a Student class for a projectChoose your own story text game that executes with loop using choices supplied by playerCourse Management with SOLID principlesExperimenting with a OOP design pattern in JavaScript

C-152 carb heat on before landing in hot weather?

Why is the voltage measurement of this circuit different when the switch is on?

What is the legal status of travelling with (unprescribed) methadone in your carry-on?

Unusual mail headers, evidence of an attempted attack. Have I been pwned?

How risky is real estate?

Why is the Turkish president's surname spelt in Russian as Эрдоган, with г?

What kind of wire should I use to pigtail an outlet?

As a DM, how do you control a dysfunctional group wanting different things out of a game?

Should my manager be aware of private LinkedIn approaches I receive? How to politely have this happen?

Do hotel cleaning personnel have any benefit from leaving empty bottles in the room as opposed to returning them to the store?

Why is there no havdallah when going from Yom Tov into Shabbat?

Catching generic Exception in a toString implementation - bad practice?

Sho, greek letter

Require advice on power conservation for backpacking trip

Are there any vegetarian astronauts?

Cascading Repair Costs following Blown Head Gasket on a 2004 Subaru Outback

Is this one of the engines from the 9/11 aircraft?

Do equal angles necessarily mean a polygon is regular?

Can ADFS connect to other SSO services?

Analog is Obtuse!

Do flight schools typically have dress codes or expectations?

STM Microcontroller burns every time

Apply brace expansion in "reverse order"

First-year PhD giving a talk among well-established researchers in the field



Object-oriented design implementation of an Elevator


Object Orientated PHP, what's wrong with this implementation of OOPHP and how might it be improved?Cinema schedulingBowling scorecard appPoker Hand classifer part 3: Deck Object and 7 Card HandLeetcode 317: Shortest distance from all buildingsPHP subset of 2 arrays containing objects - compared only by 1 attributeCreating a Student class for a projectChoose your own story text game that executes with loop using choices supplied by playerCourse Management with SOLID principlesExperimenting with a OOP design pattern in JavaScript






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








4












$begingroup$


I am a newbie when it comes to Object Oriented Programming and I have read a lot of online articles and lessons so I want to try it out on my own. I've written a console app in C# and tried implementing Object Oriented Design and SOLID Principles.



The console app checks if a person has an access to a certain floor. Also, The app is in its initial stage so right now the Elevator accomodates a single person.



Although the app works. any feedback,comments, and suggestions will be greatly appreciated especially in terms of SOLID principles or OOP Design.



here is the code below



class Program

static void Main(string[] args)

Person maintenanceEmployee = new MaintenanceEmployee();
Elevator elev = new Elevator(maintenanceEmployee);
elev.GoToFloor(Floors.FourthFloor);

Person guest = new Guest();
Elevator elev2 = new Elevator(guest);
elev2.GoToFloor(Floors.SecondFloor);

Person empfromthirdfloor = new EmployeeFromThirdFloor();
Elevator elev3 = new Elevator(empfromthirdfloor);
elev2.GoToFloor(Floors.ThirdFloor);

Console.ReadLine();



public enum Floors

FirstFloor = 1,
SecondFloor = 2,
ThirdFloor = 3,
FourthFloor = 4,
FifthFloor = 5




public class Elevator

Person person;
public Elevator(Person _person)

this.person = _person;


public void GoToFloor(Floors _floor)

if (person.HasAccess(_floor))

Console.WriteLine("Elevating to " + _floor.ToString());

else

Console.WriteLine("No Access to " + _floor.ToString());




public abstract class Person

public Floors[] accessibleFloors;

public bool HasAccess(Floors _floor)

foreach (Floors i in accessibleFloors)

if (_floor == i)

return true;


return false;




public class MaintenanceEmployee : Person

public Floors[] _accessibleFloors = Floors.FirstFloor, Floors.SecondFloor, Floors.ThirdFloor, Floors.FourthFloor, Floors.FifthFloor ;

public MaintenanceEmployee()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//in the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class EmployeeFromThirdFloor : Person

public Floors[] _accessibleFloors = Floors.ThirdFloor ;

public EmployeeFromThirdFloor()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class Guest : Person

public Floors[] _accessibleFloors = Floors.SecondFloor ;

public Guest()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;











share|improve this question









New contributor



doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$







  • 1




    $begingroup$
    Is it safe to assume an elevator can at most contain 1 person?
    $endgroup$
    – dfhwze
    Jun 15 at 9:43






  • 1




    $begingroup$
    Please add a description about what you application does. Elevator Sample is too general.
    $endgroup$
    – t3chb0t
    Jun 15 at 9:56










  • $begingroup$
    @dfwze well for now this is just its initial design, at this stage I just like to know if the coding is on track in terms of OOP or SOLID.
    $endgroup$
    – doctorWeird
    Jun 15 at 10:04

















4












$begingroup$


I am a newbie when it comes to Object Oriented Programming and I have read a lot of online articles and lessons so I want to try it out on my own. I've written a console app in C# and tried implementing Object Oriented Design and SOLID Principles.



The console app checks if a person has an access to a certain floor. Also, The app is in its initial stage so right now the Elevator accomodates a single person.



Although the app works. any feedback,comments, and suggestions will be greatly appreciated especially in terms of SOLID principles or OOP Design.



here is the code below



class Program

static void Main(string[] args)

Person maintenanceEmployee = new MaintenanceEmployee();
Elevator elev = new Elevator(maintenanceEmployee);
elev.GoToFloor(Floors.FourthFloor);

Person guest = new Guest();
Elevator elev2 = new Elevator(guest);
elev2.GoToFloor(Floors.SecondFloor);

Person empfromthirdfloor = new EmployeeFromThirdFloor();
Elevator elev3 = new Elevator(empfromthirdfloor);
elev2.GoToFloor(Floors.ThirdFloor);

Console.ReadLine();



public enum Floors

FirstFloor = 1,
SecondFloor = 2,
ThirdFloor = 3,
FourthFloor = 4,
FifthFloor = 5




public class Elevator

Person person;
public Elevator(Person _person)

this.person = _person;


public void GoToFloor(Floors _floor)

if (person.HasAccess(_floor))

Console.WriteLine("Elevating to " + _floor.ToString());

else

Console.WriteLine("No Access to " + _floor.ToString());




public abstract class Person

public Floors[] accessibleFloors;

public bool HasAccess(Floors _floor)

foreach (Floors i in accessibleFloors)

if (_floor == i)

return true;


return false;




public class MaintenanceEmployee : Person

public Floors[] _accessibleFloors = Floors.FirstFloor, Floors.SecondFloor, Floors.ThirdFloor, Floors.FourthFloor, Floors.FifthFloor ;

public MaintenanceEmployee()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//in the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class EmployeeFromThirdFloor : Person

public Floors[] _accessibleFloors = Floors.ThirdFloor ;

public EmployeeFromThirdFloor()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class Guest : Person

public Floors[] _accessibleFloors = Floors.SecondFloor ;

public Guest()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;











share|improve this question









New contributor



doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$







  • 1




    $begingroup$
    Is it safe to assume an elevator can at most contain 1 person?
    $endgroup$
    – dfhwze
    Jun 15 at 9:43






  • 1




    $begingroup$
    Please add a description about what you application does. Elevator Sample is too general.
    $endgroup$
    – t3chb0t
    Jun 15 at 9:56










  • $begingroup$
    @dfwze well for now this is just its initial design, at this stage I just like to know if the coding is on track in terms of OOP or SOLID.
    $endgroup$
    – doctorWeird
    Jun 15 at 10:04













4












4








4





$begingroup$


I am a newbie when it comes to Object Oriented Programming and I have read a lot of online articles and lessons so I want to try it out on my own. I've written a console app in C# and tried implementing Object Oriented Design and SOLID Principles.



The console app checks if a person has an access to a certain floor. Also, The app is in its initial stage so right now the Elevator accomodates a single person.



Although the app works. any feedback,comments, and suggestions will be greatly appreciated especially in terms of SOLID principles or OOP Design.



here is the code below



class Program

static void Main(string[] args)

Person maintenanceEmployee = new MaintenanceEmployee();
Elevator elev = new Elevator(maintenanceEmployee);
elev.GoToFloor(Floors.FourthFloor);

Person guest = new Guest();
Elevator elev2 = new Elevator(guest);
elev2.GoToFloor(Floors.SecondFloor);

Person empfromthirdfloor = new EmployeeFromThirdFloor();
Elevator elev3 = new Elevator(empfromthirdfloor);
elev2.GoToFloor(Floors.ThirdFloor);

Console.ReadLine();



public enum Floors

FirstFloor = 1,
SecondFloor = 2,
ThirdFloor = 3,
FourthFloor = 4,
FifthFloor = 5




public class Elevator

Person person;
public Elevator(Person _person)

this.person = _person;


public void GoToFloor(Floors _floor)

if (person.HasAccess(_floor))

Console.WriteLine("Elevating to " + _floor.ToString());

else

Console.WriteLine("No Access to " + _floor.ToString());




public abstract class Person

public Floors[] accessibleFloors;

public bool HasAccess(Floors _floor)

foreach (Floors i in accessibleFloors)

if (_floor == i)

return true;


return false;




public class MaintenanceEmployee : Person

public Floors[] _accessibleFloors = Floors.FirstFloor, Floors.SecondFloor, Floors.ThirdFloor, Floors.FourthFloor, Floors.FifthFloor ;

public MaintenanceEmployee()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//in the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class EmployeeFromThirdFloor : Person

public Floors[] _accessibleFloors = Floors.ThirdFloor ;

public EmployeeFromThirdFloor()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class Guest : Person

public Floors[] _accessibleFloors = Floors.SecondFloor ;

public Guest()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;











share|improve this question









New contributor



doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$




I am a newbie when it comes to Object Oriented Programming and I have read a lot of online articles and lessons so I want to try it out on my own. I've written a console app in C# and tried implementing Object Oriented Design and SOLID Principles.



The console app checks if a person has an access to a certain floor. Also, The app is in its initial stage so right now the Elevator accomodates a single person.



Although the app works. any feedback,comments, and suggestions will be greatly appreciated especially in terms of SOLID principles or OOP Design.



here is the code below



class Program

static void Main(string[] args)

Person maintenanceEmployee = new MaintenanceEmployee();
Elevator elev = new Elevator(maintenanceEmployee);
elev.GoToFloor(Floors.FourthFloor);

Person guest = new Guest();
Elevator elev2 = new Elevator(guest);
elev2.GoToFloor(Floors.SecondFloor);

Person empfromthirdfloor = new EmployeeFromThirdFloor();
Elevator elev3 = new Elevator(empfromthirdfloor);
elev2.GoToFloor(Floors.ThirdFloor);

Console.ReadLine();



public enum Floors

FirstFloor = 1,
SecondFloor = 2,
ThirdFloor = 3,
FourthFloor = 4,
FifthFloor = 5




public class Elevator

Person person;
public Elevator(Person _person)

this.person = _person;


public void GoToFloor(Floors _floor)

if (person.HasAccess(_floor))

Console.WriteLine("Elevating to " + _floor.ToString());

else

Console.WriteLine("No Access to " + _floor.ToString());




public abstract class Person

public Floors[] accessibleFloors;

public bool HasAccess(Floors _floor)

foreach (Floors i in accessibleFloors)

if (_floor == i)

return true;


return false;




public class MaintenanceEmployee : Person

public Floors[] _accessibleFloors = Floors.FirstFloor, Floors.SecondFloor, Floors.ThirdFloor, Floors.FourthFloor, Floors.FifthFloor ;

public MaintenanceEmployee()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//in the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class EmployeeFromThirdFloor : Person

public Floors[] _accessibleFloors = Floors.ThirdFloor ;

public EmployeeFromThirdFloor()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;



public class Guest : Person

public Floors[] _accessibleFloors = Floors.SecondFloor ;

public Guest()

//Not sure if this is the best practice
//Reason why I did it like this is because
//I need to change the arrays of accessibleFloors
//of the abstract class "Person" in order to run successfully
base.accessibleFloors = _accessibleFloors;








c# beginner object-oriented






share|improve this question









New contributor



doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question









New contributor



doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question








edited Jun 15 at 11:53









t3chb0t

36k7 gold badges58 silver badges133 bronze badges




36k7 gold badges58 silver badges133 bronze badges






New contributor



doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked Jun 15 at 9:11









doctorWeirddoctorWeird

294 bronze badges




294 bronze badges




New contributor



doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




doctorWeird is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









  • 1




    $begingroup$
    Is it safe to assume an elevator can at most contain 1 person?
    $endgroup$
    – dfhwze
    Jun 15 at 9:43






  • 1




    $begingroup$
    Please add a description about what you application does. Elevator Sample is too general.
    $endgroup$
    – t3chb0t
    Jun 15 at 9:56










  • $begingroup$
    @dfwze well for now this is just its initial design, at this stage I just like to know if the coding is on track in terms of OOP or SOLID.
    $endgroup$
    – doctorWeird
    Jun 15 at 10:04












  • 1




    $begingroup$
    Is it safe to assume an elevator can at most contain 1 person?
    $endgroup$
    – dfhwze
    Jun 15 at 9:43






  • 1




    $begingroup$
    Please add a description about what you application does. Elevator Sample is too general.
    $endgroup$
    – t3chb0t
    Jun 15 at 9:56










  • $begingroup$
    @dfwze well for now this is just its initial design, at this stage I just like to know if the coding is on track in terms of OOP or SOLID.
    $endgroup$
    – doctorWeird
    Jun 15 at 10:04







1




1




$begingroup$
Is it safe to assume an elevator can at most contain 1 person?
$endgroup$
– dfhwze
Jun 15 at 9:43




$begingroup$
Is it safe to assume an elevator can at most contain 1 person?
$endgroup$
– dfhwze
Jun 15 at 9:43




1




1




$begingroup$
Please add a description about what you application does. Elevator Sample is too general.
$endgroup$
– t3chb0t
Jun 15 at 9:56




$begingroup$
Please add a description about what you application does. Elevator Sample is too general.
$endgroup$
– t3chb0t
Jun 15 at 9:56












$begingroup$
@dfwze well for now this is just its initial design, at this stage I just like to know if the coding is on track in terms of OOP or SOLID.
$endgroup$
– doctorWeird
Jun 15 at 10:04




$begingroup$
@dfwze well for now this is just its initial design, at this stage I just like to know if the coding is on track in terms of OOP or SOLID.
$endgroup$
– doctorWeird
Jun 15 at 10:04










2 Answers
2






active

oldest

votes


















3












$begingroup$

Person + Derived Classes




  • accessibleFloors is a breach of Open–closed principle. Anyone is able to modiy this collection.


  • accessibleFloors could be considered a breach of Single responsibility principle. Consider having a Role class and Person storing his Roles set. This way, you can also mitigate redundant code and remove the need of derived classes as EmployeeFromThirdFloor, Guest and MaintenanceEmployee (in this trivial example these classes are not required).


  • accessibleFloors can be null. The code is not able to handle this situation.


  • HasAccess is way to convoluted: accessibleFloors.Contains(_floor); would do it.


public abstract class Person

public Floors[] accessibleFloors;

public bool HasAccess(Floors _floor)

foreach (Floors i in accessibleFloors)

if (_floor == i)

return true;


return false;





We can create a class Role.



public class Role 

public HashSet<Floors> AccessibleFloors get;

public Role (HashSet<Floors> accessibleFloors)

AccessibleFloors = accessibleFloors
?? throw new ArgumentNullException(nameof(accessibleFloors));


public bool HasAccess(Floor floor)

return AccessibleFloors.Contains(floor);


// override equals and gethashcode ..



We can refactor Person.



public class Person

public HashSet<Role> Roles get;

public Person(HashSet roles)
Roles = roles ?? throw new ArgumentNullException(nameof(roles));


public bool HasAccess(Floors floor)

return Roles.Any(r => r.HasAccess(floor));




Because of Inheritance, the derived classes do not require to create their own instance variable _accessibleFloors.




base.accessibleFloors = _accessibleFloors;





Elevator



  • There is tight-coupling between an Elevator and a Person. You force the elevator to exist only with a person. What about an empty elevator.


  • GoToFloor is not usable code. Consider returning a Boolean and putting the Console.WriteLine in the calling code.

  • The code cannot handle when Person is null.


public class Elevator

Person person;
public Elevator(Person _person)

this.person = _person;


public void GoToFloor(Floors _floor)

if (person.HasAccess(_floor))

Console.WriteLine("Elevating to " + _floor.ToString());

else

Console.WriteLine("No Access to " + _floor.ToString());






Elevator could be refactored as follows.



public class Elevator

public Person Person get; private set;

public bool IsFull => Person != null;
public bool IsEmpty => Person == null;

public bool Enter(Person person)

if (person == null) throw new ArgumentNullException(nameof(person));
if (IsFull) return false;
Person = person;
return true;


public bool Exit(Floors floor)

if (IsEmpty) return false;
if (!Person.HasAccess(floor)) return false;
Person = null;
return true;





Program



class Program

static void Main(string[] args)

var guestRoles = new HashSet<Role>
new Role(new HashSet<Floors> Floors.FirstFloor )
;
var guest = new Person(guestRoles);
var elevator = new Elevator();

if (elevator.Enter(guest))

Console.WriteLine("guest has entered elevator");

else

Console.WriteLine("guest cannot enter elevator: elevator is full");


if (elevator.Exit(Floors.FirstFloor))

Console.WriteLine("guest has exited elevator at FirstFloor");

else

Console.WriteLine("guest cannot exit elevator at FirstFloor: access is denied");


Console.ReadLine();







share|improve this answer











$endgroup$








  • 1




    $begingroup$
    wow, I appreciate the remodelling and refactoring of the code. Thank you.
    $endgroup$
    – doctorWeird
    Jun 15 at 11:33


















3












$begingroup$

If I may add a single consideration to dfhwze's thorough answer:



Having an enum defining floors is OK for a building with 5 floors, but would be overwhelming if we are talking Burj Khalifa with its 163 floors. Besides that it is a rather rigid concept having a predefined number of floors - supposed you want to reuse your object model for other buildings.



Therefore I would create a Floor class too:



public class Floor

private Floor(string name, int index)

Name = name;
Index = index;


public string Name get;
public int Index get;

public static IEnumerable<Floor> CreateFloors(params string[] names)

return names.Select((n, i) => new Floor(n, i));







share|improve this answer









$endgroup$















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    doctorWeird is a new contributor. Be nice, and check out our Code of Conduct.









    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f222345%2fobject-oriented-design-implementation-of-an-elevator%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3












    $begingroup$

    Person + Derived Classes




    • accessibleFloors is a breach of Open–closed principle. Anyone is able to modiy this collection.


    • accessibleFloors could be considered a breach of Single responsibility principle. Consider having a Role class and Person storing his Roles set. This way, you can also mitigate redundant code and remove the need of derived classes as EmployeeFromThirdFloor, Guest and MaintenanceEmployee (in this trivial example these classes are not required).


    • accessibleFloors can be null. The code is not able to handle this situation.


    • HasAccess is way to convoluted: accessibleFloors.Contains(_floor); would do it.


    public abstract class Person

    public Floors[] accessibleFloors;

    public bool HasAccess(Floors _floor)

    foreach (Floors i in accessibleFloors)

    if (_floor == i)

    return true;


    return false;





    We can create a class Role.



    public class Role 

    public HashSet<Floors> AccessibleFloors get;

    public Role (HashSet<Floors> accessibleFloors)

    AccessibleFloors = accessibleFloors
    ?? throw new ArgumentNullException(nameof(accessibleFloors));


    public bool HasAccess(Floor floor)

    return AccessibleFloors.Contains(floor);


    // override equals and gethashcode ..



    We can refactor Person.



    public class Person

    public HashSet<Role> Roles get;

    public Person(HashSet roles)
    Roles = roles ?? throw new ArgumentNullException(nameof(roles));


    public bool HasAccess(Floors floor)

    return Roles.Any(r => r.HasAccess(floor));




    Because of Inheritance, the derived classes do not require to create their own instance variable _accessibleFloors.




    base.accessibleFloors = _accessibleFloors;





    Elevator



    • There is tight-coupling between an Elevator and a Person. You force the elevator to exist only with a person. What about an empty elevator.


    • GoToFloor is not usable code. Consider returning a Boolean and putting the Console.WriteLine in the calling code.

    • The code cannot handle when Person is null.


    public class Elevator

    Person person;
    public Elevator(Person _person)

    this.person = _person;


    public void GoToFloor(Floors _floor)

    if (person.HasAccess(_floor))

    Console.WriteLine("Elevating to " + _floor.ToString());

    else

    Console.WriteLine("No Access to " + _floor.ToString());






    Elevator could be refactored as follows.



    public class Elevator

    public Person Person get; private set;

    public bool IsFull => Person != null;
    public bool IsEmpty => Person == null;

    public bool Enter(Person person)

    if (person == null) throw new ArgumentNullException(nameof(person));
    if (IsFull) return false;
    Person = person;
    return true;


    public bool Exit(Floors floor)

    if (IsEmpty) return false;
    if (!Person.HasAccess(floor)) return false;
    Person = null;
    return true;





    Program



    class Program

    static void Main(string[] args)

    var guestRoles = new HashSet<Role>
    new Role(new HashSet<Floors> Floors.FirstFloor )
    ;
    var guest = new Person(guestRoles);
    var elevator = new Elevator();

    if (elevator.Enter(guest))

    Console.WriteLine("guest has entered elevator");

    else

    Console.WriteLine("guest cannot enter elevator: elevator is full");


    if (elevator.Exit(Floors.FirstFloor))

    Console.WriteLine("guest has exited elevator at FirstFloor");

    else

    Console.WriteLine("guest cannot exit elevator at FirstFloor: access is denied");


    Console.ReadLine();







    share|improve this answer











    $endgroup$








    • 1




      $begingroup$
      wow, I appreciate the remodelling and refactoring of the code. Thank you.
      $endgroup$
      – doctorWeird
      Jun 15 at 11:33















    3












    $begingroup$

    Person + Derived Classes




    • accessibleFloors is a breach of Open–closed principle. Anyone is able to modiy this collection.


    • accessibleFloors could be considered a breach of Single responsibility principle. Consider having a Role class and Person storing his Roles set. This way, you can also mitigate redundant code and remove the need of derived classes as EmployeeFromThirdFloor, Guest and MaintenanceEmployee (in this trivial example these classes are not required).


    • accessibleFloors can be null. The code is not able to handle this situation.


    • HasAccess is way to convoluted: accessibleFloors.Contains(_floor); would do it.


    public abstract class Person

    public Floors[] accessibleFloors;

    public bool HasAccess(Floors _floor)

    foreach (Floors i in accessibleFloors)

    if (_floor == i)

    return true;


    return false;





    We can create a class Role.



    public class Role 

    public HashSet<Floors> AccessibleFloors get;

    public Role (HashSet<Floors> accessibleFloors)

    AccessibleFloors = accessibleFloors
    ?? throw new ArgumentNullException(nameof(accessibleFloors));


    public bool HasAccess(Floor floor)

    return AccessibleFloors.Contains(floor);


    // override equals and gethashcode ..



    We can refactor Person.



    public class Person

    public HashSet<Role> Roles get;

    public Person(HashSet roles)
    Roles = roles ?? throw new ArgumentNullException(nameof(roles));


    public bool HasAccess(Floors floor)

    return Roles.Any(r => r.HasAccess(floor));




    Because of Inheritance, the derived classes do not require to create their own instance variable _accessibleFloors.




    base.accessibleFloors = _accessibleFloors;





    Elevator



    • There is tight-coupling between an Elevator and a Person. You force the elevator to exist only with a person. What about an empty elevator.


    • GoToFloor is not usable code. Consider returning a Boolean and putting the Console.WriteLine in the calling code.

    • The code cannot handle when Person is null.


    public class Elevator

    Person person;
    public Elevator(Person _person)

    this.person = _person;


    public void GoToFloor(Floors _floor)

    if (person.HasAccess(_floor))

    Console.WriteLine("Elevating to " + _floor.ToString());

    else

    Console.WriteLine("No Access to " + _floor.ToString());






    Elevator could be refactored as follows.



    public class Elevator

    public Person Person get; private set;

    public bool IsFull => Person != null;
    public bool IsEmpty => Person == null;

    public bool Enter(Person person)

    if (person == null) throw new ArgumentNullException(nameof(person));
    if (IsFull) return false;
    Person = person;
    return true;


    public bool Exit(Floors floor)

    if (IsEmpty) return false;
    if (!Person.HasAccess(floor)) return false;
    Person = null;
    return true;





    Program



    class Program

    static void Main(string[] args)

    var guestRoles = new HashSet<Role>
    new Role(new HashSet<Floors> Floors.FirstFloor )
    ;
    var guest = new Person(guestRoles);
    var elevator = new Elevator();

    if (elevator.Enter(guest))

    Console.WriteLine("guest has entered elevator");

    else

    Console.WriteLine("guest cannot enter elevator: elevator is full");


    if (elevator.Exit(Floors.FirstFloor))

    Console.WriteLine("guest has exited elevator at FirstFloor");

    else

    Console.WriteLine("guest cannot exit elevator at FirstFloor: access is denied");


    Console.ReadLine();







    share|improve this answer











    $endgroup$








    • 1




      $begingroup$
      wow, I appreciate the remodelling and refactoring of the code. Thank you.
      $endgroup$
      – doctorWeird
      Jun 15 at 11:33













    3












    3








    3





    $begingroup$

    Person + Derived Classes




    • accessibleFloors is a breach of Open–closed principle. Anyone is able to modiy this collection.


    • accessibleFloors could be considered a breach of Single responsibility principle. Consider having a Role class and Person storing his Roles set. This way, you can also mitigate redundant code and remove the need of derived classes as EmployeeFromThirdFloor, Guest and MaintenanceEmployee (in this trivial example these classes are not required).


    • accessibleFloors can be null. The code is not able to handle this situation.


    • HasAccess is way to convoluted: accessibleFloors.Contains(_floor); would do it.


    public abstract class Person

    public Floors[] accessibleFloors;

    public bool HasAccess(Floors _floor)

    foreach (Floors i in accessibleFloors)

    if (_floor == i)

    return true;


    return false;





    We can create a class Role.



    public class Role 

    public HashSet<Floors> AccessibleFloors get;

    public Role (HashSet<Floors> accessibleFloors)

    AccessibleFloors = accessibleFloors
    ?? throw new ArgumentNullException(nameof(accessibleFloors));


    public bool HasAccess(Floor floor)

    return AccessibleFloors.Contains(floor);


    // override equals and gethashcode ..



    We can refactor Person.



    public class Person

    public HashSet<Role> Roles get;

    public Person(HashSet roles)
    Roles = roles ?? throw new ArgumentNullException(nameof(roles));


    public bool HasAccess(Floors floor)

    return Roles.Any(r => r.HasAccess(floor));




    Because of Inheritance, the derived classes do not require to create their own instance variable _accessibleFloors.




    base.accessibleFloors = _accessibleFloors;





    Elevator



    • There is tight-coupling between an Elevator and a Person. You force the elevator to exist only with a person. What about an empty elevator.


    • GoToFloor is not usable code. Consider returning a Boolean and putting the Console.WriteLine in the calling code.

    • The code cannot handle when Person is null.


    public class Elevator

    Person person;
    public Elevator(Person _person)

    this.person = _person;


    public void GoToFloor(Floors _floor)

    if (person.HasAccess(_floor))

    Console.WriteLine("Elevating to " + _floor.ToString());

    else

    Console.WriteLine("No Access to " + _floor.ToString());






    Elevator could be refactored as follows.



    public class Elevator

    public Person Person get; private set;

    public bool IsFull => Person != null;
    public bool IsEmpty => Person == null;

    public bool Enter(Person person)

    if (person == null) throw new ArgumentNullException(nameof(person));
    if (IsFull) return false;
    Person = person;
    return true;


    public bool Exit(Floors floor)

    if (IsEmpty) return false;
    if (!Person.HasAccess(floor)) return false;
    Person = null;
    return true;





    Program



    class Program

    static void Main(string[] args)

    var guestRoles = new HashSet<Role>
    new Role(new HashSet<Floors> Floors.FirstFloor )
    ;
    var guest = new Person(guestRoles);
    var elevator = new Elevator();

    if (elevator.Enter(guest))

    Console.WriteLine("guest has entered elevator");

    else

    Console.WriteLine("guest cannot enter elevator: elevator is full");


    if (elevator.Exit(Floors.FirstFloor))

    Console.WriteLine("guest has exited elevator at FirstFloor");

    else

    Console.WriteLine("guest cannot exit elevator at FirstFloor: access is denied");


    Console.ReadLine();







    share|improve this answer











    $endgroup$



    Person + Derived Classes




    • accessibleFloors is a breach of Open–closed principle. Anyone is able to modiy this collection.


    • accessibleFloors could be considered a breach of Single responsibility principle. Consider having a Role class and Person storing his Roles set. This way, you can also mitigate redundant code and remove the need of derived classes as EmployeeFromThirdFloor, Guest and MaintenanceEmployee (in this trivial example these classes are not required).


    • accessibleFloors can be null. The code is not able to handle this situation.


    • HasAccess is way to convoluted: accessibleFloors.Contains(_floor); would do it.


    public abstract class Person

    public Floors[] accessibleFloors;

    public bool HasAccess(Floors _floor)

    foreach (Floors i in accessibleFloors)

    if (_floor == i)

    return true;


    return false;





    We can create a class Role.



    public class Role 

    public HashSet<Floors> AccessibleFloors get;

    public Role (HashSet<Floors> accessibleFloors)

    AccessibleFloors = accessibleFloors
    ?? throw new ArgumentNullException(nameof(accessibleFloors));


    public bool HasAccess(Floor floor)

    return AccessibleFloors.Contains(floor);


    // override equals and gethashcode ..



    We can refactor Person.



    public class Person

    public HashSet<Role> Roles get;

    public Person(HashSet roles)
    Roles = roles ?? throw new ArgumentNullException(nameof(roles));


    public bool HasAccess(Floors floor)

    return Roles.Any(r => r.HasAccess(floor));




    Because of Inheritance, the derived classes do not require to create their own instance variable _accessibleFloors.




    base.accessibleFloors = _accessibleFloors;





    Elevator



    • There is tight-coupling between an Elevator and a Person. You force the elevator to exist only with a person. What about an empty elevator.


    • GoToFloor is not usable code. Consider returning a Boolean and putting the Console.WriteLine in the calling code.

    • The code cannot handle when Person is null.


    public class Elevator

    Person person;
    public Elevator(Person _person)

    this.person = _person;


    public void GoToFloor(Floors _floor)

    if (person.HasAccess(_floor))

    Console.WriteLine("Elevating to " + _floor.ToString());

    else

    Console.WriteLine("No Access to " + _floor.ToString());






    Elevator could be refactored as follows.



    public class Elevator

    public Person Person get; private set;

    public bool IsFull => Person != null;
    public bool IsEmpty => Person == null;

    public bool Enter(Person person)

    if (person == null) throw new ArgumentNullException(nameof(person));
    if (IsFull) return false;
    Person = person;
    return true;


    public bool Exit(Floors floor)

    if (IsEmpty) return false;
    if (!Person.HasAccess(floor)) return false;
    Person = null;
    return true;





    Program



    class Program

    static void Main(string[] args)

    var guestRoles = new HashSet<Role>
    new Role(new HashSet<Floors> Floors.FirstFloor )
    ;
    var guest = new Person(guestRoles);
    var elevator = new Elevator();

    if (elevator.Enter(guest))

    Console.WriteLine("guest has entered elevator");

    else

    Console.WriteLine("guest cannot enter elevator: elevator is full");


    if (elevator.Exit(Floors.FirstFloor))

    Console.WriteLine("guest has exited elevator at FirstFloor");

    else

    Console.WriteLine("guest cannot exit elevator at FirstFloor: access is denied");


    Console.ReadLine();








    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jun 15 at 11:02

























    answered Jun 15 at 10:43









    dfhwzedfhwze

    3,1161 gold badge6 silver badges31 bronze badges




    3,1161 gold badge6 silver badges31 bronze badges







    • 1




      $begingroup$
      wow, I appreciate the remodelling and refactoring of the code. Thank you.
      $endgroup$
      – doctorWeird
      Jun 15 at 11:33












    • 1




      $begingroup$
      wow, I appreciate the remodelling and refactoring of the code. Thank you.
      $endgroup$
      – doctorWeird
      Jun 15 at 11:33







    1




    1




    $begingroup$
    wow, I appreciate the remodelling and refactoring of the code. Thank you.
    $endgroup$
    – doctorWeird
    Jun 15 at 11:33




    $begingroup$
    wow, I appreciate the remodelling and refactoring of the code. Thank you.
    $endgroup$
    – doctorWeird
    Jun 15 at 11:33













    3












    $begingroup$

    If I may add a single consideration to dfhwze's thorough answer:



    Having an enum defining floors is OK for a building with 5 floors, but would be overwhelming if we are talking Burj Khalifa with its 163 floors. Besides that it is a rather rigid concept having a predefined number of floors - supposed you want to reuse your object model for other buildings.



    Therefore I would create a Floor class too:



    public class Floor

    private Floor(string name, int index)

    Name = name;
    Index = index;


    public string Name get;
    public int Index get;

    public static IEnumerable<Floor> CreateFloors(params string[] names)

    return names.Select((n, i) => new Floor(n, i));







    share|improve this answer









    $endgroup$

















      3












      $begingroup$

      If I may add a single consideration to dfhwze's thorough answer:



      Having an enum defining floors is OK for a building with 5 floors, but would be overwhelming if we are talking Burj Khalifa with its 163 floors. Besides that it is a rather rigid concept having a predefined number of floors - supposed you want to reuse your object model for other buildings.



      Therefore I would create a Floor class too:



      public class Floor

      private Floor(string name, int index)

      Name = name;
      Index = index;


      public string Name get;
      public int Index get;

      public static IEnumerable<Floor> CreateFloors(params string[] names)

      return names.Select((n, i) => new Floor(n, i));







      share|improve this answer









      $endgroup$















        3












        3








        3





        $begingroup$

        If I may add a single consideration to dfhwze's thorough answer:



        Having an enum defining floors is OK for a building with 5 floors, but would be overwhelming if we are talking Burj Khalifa with its 163 floors. Besides that it is a rather rigid concept having a predefined number of floors - supposed you want to reuse your object model for other buildings.



        Therefore I would create a Floor class too:



        public class Floor

        private Floor(string name, int index)

        Name = name;
        Index = index;


        public string Name get;
        public int Index get;

        public static IEnumerable<Floor> CreateFloors(params string[] names)

        return names.Select((n, i) => new Floor(n, i));







        share|improve this answer









        $endgroup$



        If I may add a single consideration to dfhwze's thorough answer:



        Having an enum defining floors is OK for a building with 5 floors, but would be overwhelming if we are talking Burj Khalifa with its 163 floors. Besides that it is a rather rigid concept having a predefined number of floors - supposed you want to reuse your object model for other buildings.



        Therefore I would create a Floor class too:



        public class Floor

        private Floor(string name, int index)

        Name = name;
        Index = index;


        public string Name get;
        public int Index get;

        public static IEnumerable<Floor> CreateFloors(params string[] names)

        return names.Select((n, i) => new Floor(n, i));








        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jun 15 at 12:37









        Henrik HansenHenrik Hansen

        9,5581 gold badge13 silver badges34 bronze badges




        9,5581 gold badge13 silver badges34 bronze badges




















            doctorWeird is a new contributor. Be nice, and check out our Code of Conduct.









            draft saved

            draft discarded


















            doctorWeird is a new contributor. Be nice, and check out our Code of Conduct.












            doctorWeird is a new contributor. Be nice, and check out our Code of Conduct.











            doctorWeird is a new contributor. Be nice, and check out our Code of Conduct.














            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f222345%2fobject-oriented-design-implementation-of-an-elevator%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

            Circuit construction for execution of conditional statements using least significant bitHow are two different registers being used as “control”?How exactly is the stated composite state of the two registers being produced using the $R_zz$ controlled rotations?Efficiently performing controlled rotations in HHLWould this quantum algorithm implementation work?How to prepare a superposed states of odd integers from $1$ to $sqrtN$?Why is this implementation of the order finding algorithm not working?Circuit construction for Hamiltonian simulationHow can I invert the least significant bit of a certain term of a superposed state?Implementing an oracleImplementing a controlled sum operation

            Magento 2 “No Payment Methods” in Admin New OrderHow to integrate Paypal Express Checkout with the Magento APIMagento 1.5 - Sales > Order > edit order and shipping methods disappearAuto Invoice Check/Money Order Payment methodAdd more simple payment methods?Shipping methods not showingWhat should I do to change payment methods if changing the configuration has no effects?1.9 - No Payment Methods showing upMy Payment Methods not Showing for downloadable/virtual product when checkout?Magento2 API to access internal payment methodHow to call an existing payment methods in the registration form?