Reputation: 149
SRP: "It says that your class, or method should do only one thing"
When do I know my method is doing more than one thing?
Example:
I have a class Bus
with a List<Passenger>
and a enum BusState
in it. The state of the Bus
depends on the size of List<Passenger>
.
public void addPassenger(Passenger p){
this.passengerList.add(p);
if (passengerList.size < 10)
this.state = BusState.EMPTY;
else if (passengerList.size < 30)
this.state = BusState.HALF_FULL;
else if (passengerList.size >= 30)
this.state = BusState.FULL;
}
And even if I refactor this:
public void addPassenger(Passenger p){
this.passengerList.add(p);
changeBusState();
}
private void changeBusState(){
if (passengerList.size < 10)
this.state = BusState.EMPTY;
else if (passengerList.size < 30)
this.state = BusState.HALF_FULL;
else if (passengerList.size >= 30)
this.state = BusState.FULL;
}
In my opinion the method addPassenger()
is doing more than one thing:
- adding a new passenger to the List
- checking the current number of passengers
- changing the state of the bus if necessary
How can I understand the SRP? Is this method doing more than one thing?
Upvotes: 2
Views: 2419
Reputation: 1
The previous answers are useful, but I'll add some more for those who find this later.
The correct way to solve the problem is exactly what the question poster did. The only other thing I would do is changing the name of the function from addPassenger to addPassengerToBus (or boardBus).
Adding a passenger to the bus should change the fullness of the bus. You would never want to have someone added to the bus without calculating the change in bus fullness. From the "business" perspective (the business of busses) it is one thing.
What is not one thing, is the exact numerical tipping points, which should be calculated via it's own function and called whenever a passenger is added.
Had adding people to the bus truly been independent of calculating the fullness of the bus, then the thing to do would be to split the functions and have the method which calls addPassenger now call both methods directly.
Upvotes: 0
Reputation: 35911
Robert Martin explains the "one thing" as "one business reason to change". There is no universal definition of "one" for all code bases because the APIs we create work on different abstraction levels. So it all depends on who is the client of your class, and what changes they might require.
In your case in makes sense to say that the method is doing two things: it manages the contents of the bus and calculates the state. Thus it can have two reasons to change:
different business logic for adding passengers: for example one might wish to verify that there is enough place in the bus for yet another passenger and throw an exception if not
different business logic regarding the semantics of BusState
(simplest example: one might wish that full bus starts from 31 passengers, not 30)
In this context you could change addPassenger
to focus on adding only:
public void addPassenger(Passenger p){
this.passengerList.add(p);
}
and change the BusState
getter to perform calculations on demand (similarly to what Sweeper proposed in their answer):
public BusState getBusState() {
if (passengerList.size < 10)
return BusState.EMPTY;
else if (passengerList.size < 30)
return BusState.HALF_FULL;
else if (passengerList.size >= 30)
return BusState.FULL;
else
throw ...
}
Upvotes: 3
Reputation: 273540
I would agree that addPassenger
is doing more than 1 thing.
One way to make it do only one thing is to delete the state
field and have a getState
method that returns a state based on how many passengers there are (assuming you are writing in Java and BusState
is an enum):
public BusState getState() {
if (passengerList.size < 10)
return BusState.EMPTY;
else if (passengerList.size < 30)
return BusState.HALF_FULL;
else if (passengerList.size >= 30)
return BusState.FULL;
else
return BusState.UNKNOWN; // somehow the no. of passengers is negative? You can consider throwing an exception here as well...
}
Upvotes: 4