How do I know when to use an enum or a sub-class? - class

Let's say I am making a game of chess. Would it be more effective to have a base class of Piece()? With sub-classes for each type of piece.
Or, an enum
enum Piece{
King,
Queen,
Knight,
etc;
}
It also brings me onto a common problem I have when refining data.
GameObjects
Piece extends GameObjects
Should I stop here and declare the objects with their individual properties?
Piece King = new Piece("King",5,10); //just made up values, no significance.
Or refine it further and have:
King extends Piece
and then handle King Pieces in a polymorphic way:
Piece king = new King("King,5,10);
thanks

Polymorphism
It depends on how you want to structure the logic of your game, but it probably makes sense to define common behavior (methods) and attributes (fields) in an abstract Piece class and then have each subtype implement abstract methods (or override default methods) and set values of inherited fields based on the ways that they vary. Maybe something like:
public abstract class Piece {
protected int value;
public int getValue() {
return value;
}
public abstract boolean isValidMove(String move);
public void move(String move) {
//common logic here
doMove(move);
}
protected abstract void doMove(String move);
}
public class King extends Piece {
public King() {
this.value = 20;
}
public boolean isValidMove(String move) {
//specific king logic here
}
protected void doMove(String move) {
//more specific king logic
}
}
This would allow you to use polymorphism to define various pieces with a common Piece API, while the important differences are handled by each concrete type.
Piece king = new King();
//...
if(king.isValidMove(move)) king.move(move);
Enums
Enums allow you to create a set of optimized singleton instances of a common type, which can also define behavior, but they don't support overriding/implementing type-specific behavior very well because you end up having to check which enum the current instance when implementing variations. You would also end up with a problem of only having a single KING or PAWN instance when you really need multiples of those for a game (one white king and one black king, 8 white pawns and 8 black pawns).
public enum Piece {
KING(20),
PAWN(1);
private int value;
private Piece(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public boolean isValidMove(String move) {
switch(this) {
case KING:
//king specific logic
break;
case PAWN:
//pawn specific logic
break;
}
}
public void move(String move) {
if(this == KING) {
//king specific logic
} else if(this == PAWN) {
//pawn specific logic
}
}
}
So an enum probably wouldn't work very well in this scenario.

Use an enum when there are a limited and defined number if instances.
In this case, clearly there are a defined number of pieces, so use an enum.
Note that enums can have methods just like a regular class, so enums don't have to be just "values", they can do stuff.
I would not try to cram too much into your enum, and in fact I would name it PieceType to make it clear what it represents, and perhaps have a class Piece which is an instance of a piece that has a PieceType, a location (board square) and a color.

The main distinction is that the set of sub-classes is open-ended: you or other people who use your code can create new sub-classes without breaking old code.
Enums are the opposite: other people cannot add new items to your enum and even you, the maintainer of the code, cannot add new enum constants without double-checking every single switch-case statement.
So, use enums if you do not expect new items to be added to the set. Use sub-classes otherwise. This does not mean that sub-classes are better: if you know the set of options to be closed-ended then you should NOT use sub-classes. If you do, you will find yourself writing if (... instanceof ...) chains!
If with enums you find yourself adding new cases to your switch statements (or you can anticipate that) then switch to sub-classes. And if with sub-classes, you find yourself writing instanceof chains, then switch to enums.

Related

Generic builder of (almost) identical 3rd party classes

I have a bunch of 3rd party classes, these classes are autogenerated in java and do not have any hierarchy
Here is the RulesPropertyList
enum RulesPropertyType {...}
class RulesPropertyValue {...}
class RulesProperty {
public RulesPropertyType getPropertyTypeCode(){...}
public RulesPropertyValue getPropertyValue() {...}
}
class RulesPropertyList {
public void setNumProperties(int numProperties)
public void setProperties(RulesProperty[] properties)
}
And its Characs* sibling
enum CharacsPropertyType {...}
class CharacsPropertyValue {...}
class CharacsProperty {
public CharacsPropertyType getPropertyTypeCode(){...}
public CharacsPropertyValue getPropertyValue() {...}
}
class CharacsPropertyList {
public void setNumProperties(int numProperties)
public void setProperties(CharacsProperty[] properties)
}
There are more than just Rules* and Characs* families of classes, and classes actually have more fields and deeper structures.
All classes are completely identical except for the prefixes in the class names.
Currently, I have a separate builder method for each set of classes.
def buildRulesPropertyList(props: (RulesPropertyType, RulesPropertValue): RulesPropertyList = {
val properties = props.map { case (type, value) =>
RulesProperty(type, value)
}
val propList = RulesPropertyList
propList.setProperties(properties.toArray)
propList.setNumProperties(properties.length)
propList
}
I have to create such a builder for each family of classes.
Now I only see a possibility to make a generic builder using reflection.
Is there a way in Scala to make such a builder using generics in Scala language?
Is there a way in Scala to make such a builder using generics in Scala language?
yes, but I don't think it's going to be any less code. I think your best move here is to just write some simple code generation for each type. you would feed it a list of family names like Seq("Rules", "Characs", ...) and have it spit out your build${family}PropertyList methods.

Converting UML to code c++. Problem with inheritence. Do constructors of all classes run when object of any one of them is created?

I have this UML diagram
Ad this is the corresponding C++ code
//Parent class Flight
class Flight
{
private:
int callNumber;
Airplane plane;
vector<Passenger> passengers;
public:
//Constructor
Flight();
//Functions
int getCallNum();
void setCallNum();
Airplane getPlane();
//What parameters are taken in these functions.
//I know they are of type Airplane and passenger but are they vectors?
void setPlane(Airplane);
void addPassenger(Passenger);
void removePassenger(Passenger);
};
//Airplane class, child of Flight
class Airplane : public Flight
{
private:
int firstClassSeats;
int economySeats;
public:
//Constructor
Airplane();
//Functions;
int getFirstClassSeats();
int getEconomySeats();
void setFirstClassSeats();
void setEconomySeats();
};
//Passenger class, child of FLight
class Passenger : public Flight
{
private:
string name;
int age;
string address;
public:
//Constructor
Passenger();
//Functions
string getName();
int getAge();
string getAddress();
void setName(string);
void setAge(int);
void setAddress(string);
};
I wonder:
do constructors of all classes run when an object of either parent or base class is created?
Can base class access functions or data of child classes?
I do not know how set plane function in parent class would look like. Would it take an object of type Airplane as an argument? Similarly, will addpassenger function in parent class take a vector of type Passenger as an argument?
In short
If A inherits B (or A specializes B), then you should be able to say A is a (kind of) B. When in doubt, prefer object composition over inheritance.
More details
The parameters taken by the member functions, are the parameters that you indicate for the operations in the diagram. No parameter in the diagram leads to no parameters in the code.
The inheritance here is ambigous. There is no inheritance in your diagram. There is some in your code, but it does not make so much sense: is a passenger really a flight? E.g. can a passenger fly, have a crew, etc.?
If the inheritance would be suitable, as a general rule in C++: the constructor of an object is always called when the object is created. In case of inheritance, all the constructors of the class hierarchy are invoked, starting with the base constructor, until the most derived constructor (the rules can be more tricky, for example in case of multiple inheritance). In UML, the rules on constructors are not fully specified as far as I know.
By default, a class can only access public members of another class. If a class is derived from a base class (in UML: if a class is a specialisation of a more general class), the derived class has only access to the public and protected members of the base class. Try to avoid protected, since it's a frequent cause of nasty bugs.
WHen implementing in C++ an UML class diagram, there is a tricky issue about the types of the properties and arguments, because C++ has a value semantic: if you pass an Airplane as argument, the original airplane object is copied. Same if you have an Airplane property. However, in UML, properties and associations have a reference semantic (except for datatypes), meaning that the airplane argument would still refer to the same original airplane. So in your specific case, you'd probably want to pass a reference or a (smart) pointer to an Airplane.

Class implements Interface

So I started learning Interfaces and now I'm wondering when to use
Interface i = new Class();
and when to use
Class c = new Class();
and I noticed that I can't use class methods if I do it the first way, only interface methods. Do you know why?
Sorry I'm still a noob in Java, Thanks for answering
Let me put it in simple way.
Interface defines the behavior of class and classes which implements interface will give implementations to that behavior.
Here is an example
Interface Shape
{
void draw();
}
Class Circle implements Shape
{
void draw()
{
... code to draw circle
}
void printRadius()
{
}
}
Class Rectangle implements Shape
{
void draw()
{
... code to draw rectangle
}
void printDiagonal()
{
}
}
now if you see same Shape Interface is implemented by 2 classes diffrently.
Now i can write like this
Shape shape = new Circle(); // This will allow you access only draw method
Circle circle = new Circle(); // This will allow you access all methods of circle
When you want your client/consumer to access only Shape specicfic methods like draw then use Shape shape = new Circle() else if you want Circle specific method such as printRadius then use Circle circle = new Circle()
The interfaces in OOP paradigm used to generalized common behavior across group of somewhat similar objects. Therefore then you using variable of more general type, e.g. interface you will be able to use only those common methods which interface defines. Since you should be able to assign to interface variable any of interface descendants (classes which implements given interface) and be able to work with it. Therefore while you assign
Interface i = new Class();
the only methods you will be able to access is those defined in the Interface. Additionally need to note, that variable will be dynamically binded to the runtime type, e.g. to the Class in your example, thus the calls for methods defined in you interface will be dispatched to the implementation of the class.
Also think of the following, for example you have definitions:
interface Vehicle {
public void drive();
public void stop();
}
Now if you write code:
Vehicle v = new BMW()
v.drive()
// do something else
v.stop()
it should behave same when you replace new BMW() with new Mitsubishi(), regardless the fact that probably in your BMW class you might have
class BMW {
public void listenMusic()
}
This is also called "Liskov substitution principle"
Liskov's notion of a behavioral subtype defines a notion of substitutability for objects; that is, if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.

How do you refactor a God class?

Does anyone know the best way to refactor a God-object?
Its not as simple as breaking it into a number of smaller classes, because there is a high method coupling. If I pull out one method, i usually end up pulling every other method out.
It's like Jenga. You will need patience and a steady hand, otherwise you have to recreate everything from scratch. Which is not bad, per se - sometimes one needs to throw away code.
Other advice:
Think before pulling out methods: on what data does this method operate? What responsibility does it have?
Try to maintain the interface of the god class at first and delegate calls to the new extracted classes. In the end the god class should be a pure facade without own logic. Then you can keep it for convenience or throw it away and start to use the new classes only
Unit Tests help: write tests for each method before extracting it to assure you don't break functionality
I assume "God Object" means a huge class (measured in lines of code).
The basic idea is to extract parts of its functions into other classes.
In order to find those you can look for
fields/parameters that often get used together. They might move together into a new class
methods (or parts of methods) that use only a small subset of the fields in the class, the might move into a class containing just those field.
primitive types (int, String, boolean). They often are really value objects before their coming out. Once they are value object, they often attract methods.
look at the usage of the god object. Are there different methods used by different clients? Those might go in separate interfaces. Those intefaces might in turn have separate implementations.
For actually doing these changes you should have some infrastructure and tools at your command:
Tests: Have a (possibly generated) exhaustive set of tests ready that you can run often. Be extremely careful with changes you do without tests. I do those, but limit them to things like extract method, which I can do completely with a single IDE action.
Version Control: You want to have a version control that allows you to commit every 2 minutes, without really slowing you down. SVN doesn't really work. Git does.
Mikado Method: The idea of the Mikado Method is to try a change. If it works great. If not take note what is breaking, add them as dependency to the change you started with. Rollback you changes. In the resulting graph, repeat the process with a node that has no dependencies yet. http://mikadomethod.wordpress.com/book/
According to the book "Object Oriented Metrics in Practice" by Lanza and Marinescu, The God Class design flaw refers to classes that tend to centralize the intelligence of the system. A God Class performs too much work on its own, delegating only minor details to a set of trivial classes and using the data from other classes.
The detection of a God Class is based on three main characteristics:
They heavily access data of other simpler classes, either directly or using accessor methods.
They are large and complex
They have a lot of non-communicative behavior i.e., there is a low
cohesion between the methods belonging to that class.
Refactoring a God Class is a complex task, as this disharmony is often a cumulative effect of other disharmonies that occur at the method level. Therefore, performing such a refactoring requires additional and more fine-grained information about the methods of the class, and sometimes even about its inheritance context. A first approach is to identify clusters of methods and attributes that are tied together and to extract these islands into separate classes.
Split Up God Class method from the book "Object-Oriented Reengineering Patterns" proposes to incrementally redistribute the responsibilities of the God Class either to its collaborating classes or to new classes that are pulled out of the God Class.
The book "Working Effectively with Legacy Code" presents some techniques such as Sprout Method, Sprout Class, Wrap Method to be able to test the legacy systems that can be used to support the refactoring of God Classes.
What I would do, is to sub-group methods in the God Class which utilize the same class properties as inputs or outputs. After that, I would split the class into sub-classes, where each sub-class will hold the methods in a sub-group, and the properties which these methods utilize.
That way, each new class will be smaller and more coherent (meaning that all their methods will work on similar class properties). Moreover, there will be less dependency for each new class we generated. After that, we can further reduce those dependencies since we can now understand the code better.
In general, I would say that there are a couple of different methods according to the situation at hand. As an example, let's say that you have a god class named "LoginManager" that validates user information, updates "OnlineUserService" so the user is added to the online user list, and returns login-specific data (such as Welcome screen and one time offers)to the client.
So your class will look something like this:
import java.util.ArrayList;
import java.util.List;
public class LoginManager {
public void handleLogin(String hashedUserId, String hashedUserPassword){
String userId = decryptHashedString(hashedUserId);
String userPassword = decryptHashedString(hashedUserPassword);
if(!validateUser(userId, userPassword)){ return; }
updateOnlineUserService(userId);
sendCustomizedLoginMessage(userId);
sendOneTimeOffer(userId);
}
public String decryptHashedString(String hashedString){
String userId = "";
//TODO Decrypt hashed string for 150 lines of code...
return userId;
}
public boolean validateUser(String userId, String userPassword){
//validate for 100 lines of code...
List<String> userIdList = getUserIdList();
if(!isUserIdValid(userId,userIdList)){return false;}
if(!isPasswordCorrect(userId,userPassword)){return false;}
return true;
}
private List<String> getUserIdList() {
List<String> userIdList = new ArrayList<>();
//TODO: Add implementation details
return userIdList;
}
private boolean isPasswordCorrect(String userId, String userPassword) {
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
private boolean isUserIdValid(String userId, List<String> userIdList) {
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
public void updateOnlineUserService(String userId){
//TODO updateOnlineUserService for 100 lines of code...
}
public void sendCustomizedLoginMessage(String userId){
//TODO sendCustomizedLoginMessage for 50 lines of code...
}
public void sendOneTimeOffer(String userId){
//TODO sendOneTimeOffer for 100 lines of code...
}}
Now we can see that this class will be huge and complex. It is not a God class by book definition yet, since class fields are commonly used among methods now. But for the sake of argument, we can treat it as a God class and start refactoring.
One of the solutions is to create separate small classes which are used as members in the main class. Another thing you could add, could be separating different behaviors in different interfaces and their respective classes. Hide implementation details in classes by making those methods "private". And use those interfaces in the main class to do its bidding.
So at the end, RefactoredLoginManager will look like this:
public class RefactoredLoginManager {
IDecryptHandler decryptHandler;
IValidateHandler validateHandler;
IOnlineUserServiceNotifier onlineUserServiceNotifier;
IClientDataSender clientDataSender;
public void handleLogin(String hashedUserId, String hashedUserPassword){
String userId = decryptHandler.decryptHashedString(hashedUserId);
String userPassword = decryptHandler.decryptHashedString(hashedUserPassword);
if(!validateHandler.validateUser(userId, userPassword)){ return; }
onlineUserServiceNotifier.updateOnlineUserService(userId);
clientDataSender.sendCustomizedLoginMessage(userId);
clientDataSender.sendOneTimeOffer(userId);
}
}
DecryptHandler:
public class DecryptHandler implements IDecryptHandler {
public String decryptHashedString(String hashedString){
String userId = "";
//TODO Decrypt hashed string for 150 lines of code...
return userId;
}
}
public interface IDecryptHandler {
String decryptHashedString(String hashedString);
}
ValidateHandler:
public class ValidateHandler implements IValidateHandler {
public boolean validateUser(String userId, String userPassword){
//validate for 100 lines of code...
List<String> userIdList = getUserIdList();
if(!isUserIdValid(userId,userIdList)){return false;}
if(!isPasswordCorrect(userId,userPassword)){return false;}
return true;
}
private List<String> getUserIdList() {
List<String> userIdList = new ArrayList<>();
//TODO: Add implementation details
return userIdList;
}
private boolean isPasswordCorrect(String userId, String userPassword)
{
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
private boolean isUserIdValid(String userId, List<String> userIdList)
{
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
}
Important thing to note here is that the interfaces () only has to include the methods used by other classes. So IValidateHandler looks as simple as this:
public interface IValidateHandler {
boolean validateUser(String userId, String userPassword);
}
OnlineUserServiceNotifier:
public class OnlineUserServiceNotifier implements
IOnlineUserServiceNotifier {
public void updateOnlineUserService(String userId){
//TODO updateOnlineUserService for 100 lines of code...
}
}
public interface IOnlineUserServiceNotifier {
void updateOnlineUserService(String userId);
}
ClientDataSender:
public class ClientDataSender implements IClientDataSender {
public void sendCustomizedLoginMessage(String userId){
//TODO sendCustomizedLoginMessage for 50 lines of code...
}
public void sendOneTimeOffer(String userId){
//TODO sendOneTimeOffer for 100 lines of code...
}
}
Since both methods are accessed in LoginHandler, interface has to include both methods:
public interface IClientDataSender {
void sendCustomizedLoginMessage(String userId);
void sendOneTimeOffer(String userId);
}
There are really two topics here:
Given a God class, how its members be rationally partitioned into subsets? The fundamental idea is to group elements by conceptual coherency (often indicated by frequent co-usage in client modules) and by forced dependencies. Obviously the details of this are specific to the system being refactored. The outcome is a desired partition (set of groups) of God class elements.
Given a desired partition, actually making the change. This is difficult if the code base has any scale. Doing this manually, you are almost forced to retain the God class while you modify its accessors to instead call new classes formed from the partitions. And of course you need to test, test, test because it is easy to make a mistake when manually making these changes. When all accesses to the God class are gone, you can finally remove it. This sounds great in theory but it takes a long time in practice if you are facing thousands of compilation units, and you have to get the team members to stop adding accesses to the God interface while you do this. One can, however, apply automated refactoring tools to implement this; with such a tool you specify the partition to the tool and it then modifies the code base in a reliable way. Our DMS can implement this Refactoring C++ God Classes and has been used to make such changes across systems with 3,000 compilation units.

Proper place for human-readable representation of entity-based key

First some background. We recently converted from a Zend_Db_Table-based solution to entity-based solution (Doctrine). As our application grew, the table classes grew uglier and uglier. Some of the tables used ENUM columns to store string-based keys, which were converted into human-readable strings with static methods. Something like this:
public static function getProductType($productKey)
{
if (!array_key_exists($productKey, self::$productTypes)) {
return null;
}
return self::$productTypes[$productKey];
}
public static function getProductTypes()
{
return self::$productTypes;
}
In moving to the entity-based system, I tried to avoid static methods where possible. I moved the key to value translations into a view helper and called it a day. In the end, I found that it was not sufficient, as we needed to return them in JSON objects, which occurred outside of the presentation layer (i.e. no direct access to view helpers).
Does anyone have any theories on the proper place for these types of methods? Should I create separate objects for doing the translation from key to human-readable value, implement static methods on the entity object, or something else?
Well my theory is that this should be done in the model itself. But sometimes when dealing with a complex model, I like to create a separate class that handles any special "presentation" of that model. It takes the model as an argument and encapsulates the presentation logic.
So using your example, perhaps something like this:
class Model_Product
{
public static function getAllTypes()
{
return array(/* key-value pairs */);
}
//returns non human readable value
public function getType()
{
return $this->_type;
}
}
class Model_Product_Presenter
{
protected $_model;
public function __construct(Model_Product $model)
{
$this->_model = $model;
}
//returns human readable value
public function getType()
{
$types = $this->_model->getAllTypes();
if (!array_key_exists($this->_model->type, $types)) {
return null;
}
return $types[$this->_model->type];
}
public function getDateCreated($format = "Y-m-d")
{
return date($format,$this->_model->timestamp);
}
}
You can go further and create a base presenter class to define any common tasks, i.e. converting timestamps to dates, formatting numbers, etc.
Update:
For anonymous access to a list of product types, I don't see any harm in making it the responsibility of the product model via a static method. Not all static methods are evil. In my opinion, the use of static methods for this purpose is fine, because it declares a global constant.
In a more complex scenario, I would delegate this responsibility to a separate class like Model_ProductType. Here is an example of such a complex model in production:
https://github.com/magento/magento2/blob/master/app/code/core/Mage/Catalog/Model/Product/Type.php