开发者

How to write elegant perl code without ref

Help me code this scenario better. Let's say I have a baseclass named "car", and two derived classes named "Ferrari" and "Chevrolet". Now I have an new class named "ParkingLot", which s开发者_如何学Gohould know what the car it is operating on, to customize the lot-size and other attributes.

Now back to the problem. The current codebase that Iam working on is very matured, and it's complete written in Perl OOPS. The "ParkingLot" constructor will always be passed with the car object (instantiated much before this) as an argument. The code(Parking Lot) uses this argument, does a ref on object pointer to find whether the class is "Ferrari"/"Chevrolet" and does some very specific operations based on the car Type. This example, I would say is a "tip of the iceberg" and these kind of code is littered everywhere throughout the code making it more unmaintainable.

Tommorow, if I want to add a new car, that my parking Lot should support, then it's becomes a nightmare to check for references all through the code and do the changes manually. What would you do to rework the code to make it more elegant and maintainable?


Presumably the ParkingLot is differentiating between the kinds of cars for a reason - for instance, likelihood of being stolen may differ between the two. For every distinction ParkingLot makes, try to figure out what property of car (or lack of such property) that distinction is based on and give car or its subclasses those properties instead of deciding based on class.

As a temporary measure, give Chevrolet a I'm-a-Chevy property and Ferrari an I'm-a-Ferrari property and test those.


As the first comment on the question alluded to, what you want here is polymorphism. Let the car decide how the car should behave rather than making the parking lot keep track of the behaviors of every kind of car out there. e.g., Instead of this:

package Car;

package Ferrari;
use base 'Car';

package Chevrolet;
use base 'Car';

package ParkingLot;

sub add_car {
  if (ref $car = 'Ferrari') {
    $self->park_ferrari;
  } elsif (ref $car = 'Chevrolet') {
    $self->park_chevrolet;
  } else {
    die "Unknown car model!";
  }
}

do this:

package Car;

sub park {
  # park a generic Car
}

package Ferrari;
use base 'Car';
sub park {
  # take the Ferrari for a spin before parking it
  $self->drive_fast;
  $self->SUPER::park;
}

package Chevrolet;
use base 'Car';
# No sub park defined, so it just parks like a generic Car

package ParkingLot;

sub add_car {
  $car->park;
}

Now the ParkingLot just needs to know that it has a Car and the Car knows how it should park, so you can add as many new Car subclasses as you like without ever having to modify ParkingLot.

(Note that the above is Perl-like pseudocode, not real, runnable Perl code. Many details were deliberately omitted.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜