See: LittleSimulator Let's try to keep a history for would-be OO developers wishing to retrace the development in LittleSimulatorInJavaHistory. ----- // A developing implementation of LittleSimulator public class Elevator { private int location; public Elevator(){ location = 1; } public int whatFloor(){ return(location); } public void moveMe(){ if (location == 1) location = 2; else location = 1; } } public class Person { private int location; public Person(){ location = 1; } public Person(int x){ location = x; } public int whatFloor(){ return(location); } public void getOnElevator(){ location = 0; } public void getOffElevator( int elevatorLocationX ){ location = elevatorLocationX; } } public class Spike2 { public static void main(String[] args){ Person person1 = new Person(); Person person2 = new Person(2); Elevator elevator1 = new Elevator(); person1.getOnElevator(); elevator1.moveMe(); person2.getOnElevator(); person1.getOffElevator(elevator1.whatFloor()); elevator1.moveMe(); person2.getOffElevator(elevator1.whatFloor()); } } ---- In AbbreviatedUmlAscii (omitting constructors): Elevator [location,whatFloor(),moveMe()] Person [location,whatFloor(),getOnElevator(),getOffElevator()] Spike2 *Person@,Elevator@ [main()] --------------- I was going to do a SuperAbstract description of LittleSimulator reconstructed from this code, preparatory to ModelTargeterSurface analysis. However I must be missing something: can a person choose where to get off an elevator (as opposed to asking the elevator to move to a floor)? So instead here's a SuperAbstract description of my uplifting (I'm a Brit) take on the problem domain; real-world descriptions in "quotes". ''building'': Has an immutable list of ''floor''s, sorted by their ''number''s ("one above the other"); another of ''elevator''s. Maintains the ''person'' lists for ''floors'' and ''elevators'' by setting itself as an observer of each member of the initial ''person'' list passed to the ''ground floor'' ("Tracks people moving from floor to floor, with everybody starting on the ground floor") ''person'': Has a ''waiting'' flag and a ''location'' reference which must be to either a ''floor'' or an ''elevator''. ("Must be either on a floor or in an elevator.") *''waiting'' can only be set if ''location'' is a ''floor'' and is reset when it changes to an ''elevator'' ("Isn't necessarily waiting for an elevator, stops waiting on getting into one"). *''location'' can be set from a ''floor'' to an ''elevator'' if the current ''floor'' reference of the ''elevator'' is to the current ''location'' ("Can get onto a lift - sorry, elevator - only while it's visiting the current floor..."); or from an ''elevator'' to the current ''floor'' reference of that ''elevator'' ("...and off at the floor the elevator is currently visiting."). *Changes in location are notified to the ''building'' which updates the ''person'' lists for the ''elevator'' and ''floor'' involved. ''floor'': Has an immutable integer ''number'' (heuristically known never to be 13) and an immutable list of ''elevator''s that can visit it. A mutable list of ''person''s can only contain ''person''s whose ''location'' is set to the instance; this list is initially empty except for the ''ground floor'' which receives its initial list from the ''building''. ''elevator'': Has a reference to its ''building'' and an immutable list of indexes into the ''building'''s list of ''floor''s, not necessarily a continuous sequence but guaranteed not to be resorted; and an iterable index to its position in that list. An initially empty mutable list of ''person''s can only contain ''person''s whose ''location'' is set to the instance. Now left for revision by any interested reader as not really suitable for demonstrating ModelTargeterSurface: too much domain design required as above, objects do not have a wide range of properties. But it could be an excellent problem domain for demonstrating several key aspects of practical OOP: *The top-level decision about whether or not to model real-world entities (my analysis actually collapses two entities, in that the ''person'' observer is not really the ''building'' but a singleton ''god''.) *Collections, some mutable and some not *The observer and singleton patterns *Unit tests (and their applicability to interactive programs and simulations) *Extensibility of both the design and implementation: what happens when you allow people to leave the building, add stairways; can you simulate emergency situations? - DavidWright ''Looks good but how about identifying the methods for each object at a high level, as well as the attributes. For example whatFloor() is a method of Elevator at the top.'' Give us a chance guv, I'm making this up as I go along. Also I always like to do the data design first. ''Try writing the tests first. Then you only design the data you actually need to satisfy the tests.'' [See CodeUnitTestFirst] Let's do a bit of OverTheWallProgramming - I'll design and you define the tests. Anyway it's going home time here in Blighty; over to you. [See VirtualPairProgramming] ''The tests given on LittleSimulator are ambiguous. What is our goal? Are we just modeling elevator behavior? If so, here are some tests:'' * Person pushes button on floor 1 ** Elevator moves to floor 1 and opens its doors. * Person pushes button on floor 2 ** Elevator moves to floor 2 and opens its doors. * Person pushes floor 1 button inside elevator ** Elevator closes its doors, moves to floor 1 and opens its doors. * Person pushes floor 2 button inside elevator ** Elevator closes its doors, moves to floor 2 and opens its doors. * Person A pushes button on floor 1 then person B pushes button on floor 2 ** Elevator moves to floor 1, opens its doors, waits n seconds, closes its door and moves to floor 2. * Person A pushes button on floor 2 then person B pushes button on floor 1 ** Elevator moves to floor 2, opens its doors, waits n seconds, closes its door and moves to floor 1. ''I think I can satisfy these tests without modeling people, buildings or floors.'' [If you want to do the example as ObjectOriented isn't it wise to model the basic entities?] ''I HaveThisPattern as can be seen from the above'' - DavidWright ''Only if you need to. YouArentGonnaNeedIt. The system isn't going to control people, so modeling them is probably a waste of time. None of the tests interact with the building, so I can ignore that. The floors have buttons and the elevators move between them, but the tests probably just interact with the buttons (as a person would) and the floor is probably modeled as part of the elevator's state.'' ---------------------------------------------------- ''Shouldn't the LittleSimulator be more general, ie just be an engine that takes a file (or arrays if we don't want to make it too complex) representing objects, rules and events so it could be used to simulate a bank, gas (or petrol) station etc without re-coding each time?'' It's only a SpikeSolution after all, and even as such quite tricky as this discussion demonstrates. [If it's quite tricky, perhaps there's a simpler SpikeSolution lurking. The generalization suggested might actually be simpler. More general isn't always more complex, sometimes it's the other way around.] ----------------------- ''Refactored from ModelTargeterSurface'' as it seems to belong here - DavidWright Try this domain model. * an Elevator holds Passengers with Destinations up to a Limit, and changes Floors at varying Speed. * a Passenger has a Location (either a Floor or Elevator) and a Destination Floor * a Bank is a number of Elevators servicing the same Floors and is aware of the direction of Destinations of Passengers at each * the Traffic describes the arrival of new Passengers Try these use cases. * watch the activity of a Bank of Elevators from the perspective of a Passenger waiting at a given Floor. * watch the activity of a given Elevator from the perspective of a Passenger on the Elevator. * watch the activity of a given Passenger traveling on and off the Elevators (make choices for that passenger) * run any combination of any number of these views simultainously. Here is a main program. main { // create the model bank = new Bank (10 floors, 3 elevators) traffic = new HeavyU''''''pTraffic (100 people, 5 minutes) // launch three views Elevator''''''Surface.openOn(bank.elevator(1)) Floor''''''Surface.openOn(bank.floor(1)) Passenger''''''Surface.openOn(traffic.passenger(25)) // begin the simulation bank.carry(traffic) }