It wouldn't solve the problem where sending vehicles from the depot to the first timetabled stop on a mirrored line will lead to duplicate departures.
Ah, that's what you meant. Seems like I have missunderstood this point. That's abug which needs to be fixed.
Why can't his be cleaned up? We can safely assume convoys in a mirrored route to always arrive reversed route state at the first stop in the route, just like we can always asume those to arrive in non-reversed route state at the last stop. So we can just ignore their actual reversed state at the first and last stop of a mirrored schedule.
Except from that, cleaning up does not neccessarily mean to stick with the exact internal implementation. It just means to stick with the concept and behavior from the users perspective.
- vehicles can run on a s chedule in opposite direction
- schedules can make vehicles to reverse their route at each end of the schedule
- vehicles can be sent out of the depot in alternating "reverse route" state.
I see the point in your suggestion. Operating on the base schedule plus reversed state is indeed rather error prone.
It might or might not be a good option to internally store return routes explicitly, I am not sure about this.
We will still need to represent the "reversed" state to the user.
This approach makes route iterations more easily to handle, but it adds complexity elsewhere.
I agree overall this might be slightly less error-prone, but I do not think this solves the key issue behind all of this.
At this moment, at 198 locations in the code the schedule_t::entries is used directly. Only 88 of these come from the schedule_t class by itself.
If we really want to improve reliability, we should clean this up.
At first, analyse what all these accesses actually do.
Then break these operations down into a small set of methods with well-defined behavior and make all these places in the code to use those methods.
Finally, set the schedule_t::entries attribute to be private, so new code cannot do the same mistake again.
Maintaining a small set of well-defined methods is much easier than maintaining hundreds of locations in the code that basically all do the same.
When designing these methods, we can think about if it's better to pass an index plus reversal state or to pass only an index, disregarding how the datastructure is organised internally.
In Object oriented design, you virtually never want attributes to be publicly accessible for those two exact reasons.
1. You are limited to a specific implementation, as code located elswehere will rely on it.
2. Code handling the internal state of your object will be spread all over your codebase, which is a maintainance hell.