Recently I was asked a question in an interview to design a bird flight simulator.
I went ahead and thought of strategy pattern for the simulator class and attributes like air pressure, wind velocity etc. A method would take a bird object and time and would return x,y,z coordinates.
e.g.
class Simulator
attr_accesor :bird, :air_pressure, :wind_velocity
def map_coordinates(bird, time)
...
end
...
end
and then thought about bird class:
For the bird can fly/Not fly attribute I thought about a boolean variable which would be set at initialization time. For e.g:
class Bird
attr_accessor :weight, :wing_dimension, :canfly, :height....
def initialize(weight, wing_dimension, canfly, height)
#weight = weight
#wing_dimension = wing_dimension
#canfly = canfly
#height = height
end
end
My question is from OOD point of view, it says a Bird class should use composition and use a class to encapsulate the properties required in a class. https://www.safaribooksonline.com/library/view/head-first-design/0596007124/ch01.html
So, Do I really need a class to map the canfly behavior? Can't I just have a boolean field to be initialized in this case while creating the Bird object.
Why would not that be a good design?
If not, what's the best approach and why?
In terms of OOD it's important make a comparison between association/aggregation, inheritance, composition and use. In a composition relationship the class should create object instances using the method new of the class.
Bird class has associated particular weight and height, in terms of composition a bird has two wings and a peak, which maybe can be different classes. In Wing class, wing_dimension attribute should be included as an aggregation relationship, as weight and height in bird class.
class Bird
attr_accessor :weight, :height, :rightWing, :leftWing, :peak
def initialize(weight, height)
#weight = weight
#height = height
rightWing = Wing. new
leftWing = Wing. new
peak = Peak.new
end
end
In Simulator class, for example, if you'll want to design a fly simulator, this attribute needs to be common in different classes.
To sum up, if exists an inheritance relationship between a general class, for example "Animal" with bird and fly(insect), you can make an aggregation relationship in def, and canfly as an attrinute of Animal class.
class Simulator
attr_accesor :animal, :air_pressure, :wind_velocity
def map_coordinates(animal, time)
...
end
...
end
So, Do I really need a class to map the canfly behavior? Can't I just have a Boolean field to be initialized in this case while creating the Bird object?
Why would not that be a good design? If not, what's the best approach and why?
To your first question: "Do I really need...?" That is a really good
question. In terms of Object Oriented Design, that is the very question you need to be asking yourself. In fact, that is exactly how good design decisions are made.
The fact that you also arrived at a tentative solution "Can't I just...?" means that you have identified ONE small problem that you might solve with a binary solution. bool canfly ? true : false
Let's assume, that you have looked at the big picture. You imagine that your "SIMULATOR" will have all different kinds of birds, even birds
that cannot fly, as well as those TYPICAL birds that do.
And finally, you arrive at three other, really fantastic questions.
I can't help but wonder whether or not you pulled these questions straight out of an OOA & D textbook.
1) Why would not that be a good design?
2) What would be a better design?
3) Why would the second design be better than the first
OK, I am going to try my best here. I am going to attempt to make an illustration from your approach in asking these questions, and in the way that you did. Look at the tiny footprint that all of these questions make here, in comparison to the HUGE footprint it WILL make in my post, trying to fill in all of those blanks because you have no idea how many answers those questions could generate (nor do I). That just happens to be one of the answers. Man, I hope this doesn't turn into a sprawling mess.(that's another one)
I think first, I would like to clarify one very important distinction.
The nature of these questions is not the same as the nature of the questions you would expect to find answers to in an algebra textbook. Algebra is about HOW. I discovered that the WHY
doesn't really mean anything in Algebra until you get to Calculus.
Why not this way...What way should I...How is that way better...Why is that way better...? WHY should I even care? These are the kinds of questions you find answers to in a philosophy textbook. They are the appropriate kind for OOD as well because OOD is more of a philosophy than it is a "soft science." It is my opinion, and others hold that opinion, but some think otherwise. Does that sound concrete?
Interestingly enough, that is a term used in OOD to differentiate a derived class from an Abstract class or an Interface. It is the result, but it is NOT the design. In my opinion, understanding that first is as important, if not more, than any concrete design that some might try to pass off as a good answer.
Let me ask a question also. Would you rather have your tiny footprint in your code-base or my HUGE footprint there? Because you may do what you want, that is your choice. However, let me just point something out that might change your mind. I can create an Interface lets say, and I
might call it something like this.
public Interface IEveryPossibleFlyingOperationYouOrAnyoneElseMightImagine{}; And you would probably say: That is a ridiculously long and over descriptive naming convention you have there!!! To which I would reply: Yes, but you can't even imagine how many things that Interface covers....And besides, I only ever have to write it once, because then I can do this...
IEveryPossibleFlyingOperationYouOrAnyoneElseMightImagine fly;
Then I would put that tiny little fly (also an insect that just happens to fly by the way.) in my code-base. Then, I would close it up, and HOPEFULLY never have to open it again.
Furthermore, everything that belongs to that Interface, which you know nothing about, because it has been abstracted away, and loosely coupled with other things like it, for the purpose of possible future extension, will never break your code base. How could it? It's a tiny little fly.
You see how long this answer is, and it only scratches the surface of what you are actually asking here I assure you.
Now, I will try to give you something a little more concrete, though it will not be nearly enough to satisfy all of what you are asking here.
OOP, in general, is about a lot of things, this one thing, that I hope makes at least some sense, is a principle. If that principle is learned and followed, you will never have my footprint in your code-base.
The big mystery of what is behind that interface is something that your client will never have to even know about, but I assure you that the way it is put together makes it extremely versatile and adaptive, because I built it according to tried and proven principles and patterns that other people way smarter than me figured out.
Even they don't know all of the possibilities of this paradigm because there are too many to count. They don't care anyway because they are busy solving other design issues by mixing and matching principles and patterns solving really complex problems very simply.
Also, get this, the next time you set out to design something you can put that tiny little fly in that and use it there too, and there will ever be, only one place to go to maintain and improve all that is behind that tiny little fly.
I know this is probably not the answer you were looking for, or maybe you get it already, which would be awesome. It took me forever just to figure out what the hell an object even was...but once it clicked, with the help of a really smart professor, who showed me what I tried to show here; oh..
and a book called Gang of Four; then I was able to begin, and I only wish I understood it all too.
I think if you go back and look at that article, you will be able to figure out what the other answers are, I only answered the easy one(or tried). I looked at it, and all of the information is there. It might be that you just need to look at it in a slightly different way, but you will get it if you really want to know.
I'm sorry, but that is the best I can do, and be honest at the same time. If anyone tries to tell you HOW is the answer, instead of WHY, don't listen to them, because the likely don't understand it either, but not because it's hard. It would be because they didn't start out asking the right questions like you did here. I wish you well and hope that someone else comes along who can maybe explain it better than me. +1) For asking all the right questions!
I have a question regarding OOP. I'm not new to Delphi, but I learned it by myself, mostly from the internet and didn't learned it the "correct" way. I just started to take a look at OOP some weeks ago. So this is my problem:
I have an own Class called "Session". This class is connected with Edits through Visual LiveBindings. I want to fill my class with data from a TClientDataset (there is a reason why I don't bind the dataset with the edits directly). Now I have 2 ideas:
1. I build another class which implements the Dataset and handles the opening of files and Navigation.
2. I Drag and drop the ClientDataset one my Form and connect it to my class with Livebindings, like this: DataSet <---> Class <---> Edit
I hope you understand my description. So: Which idea is better? I have the feeling that LiveBindings "destroy" the Concept of OOP. On the other hand I don't need to write Code and typecast, because the live bindings do that for me.
So which way would you choose and why? Or has somebody another idea?
I hope you understand what I mean and can help me :)
With LiveBindings it is perfectly possible to bind to objects instead of datasets.
See: http://www.malcolmgroves.com/blog/?p=1084
In summary: take look at TAdapterBindSource component. It is designed for creating LiveBindings between existing controls and custom objects. In it's onCreateAdapter event you can return a TObjectBindSourceAdapter as aBindSourceAdapter in case you want to bind one specific object, or return a TListBindSourceAdapter for binding list of objects.
LiveBindings and OOP does not bite each other!
The title pretty much says it. What I really want is a layer mode that takes the alpha channel of the one below it and in all other respects behaves the same. The general question seems worth asking.
I'm skimming the docs, and it seems like layer modes are a fixed enum, but I wan't to be sure there isn't something I'm overlooking. I'll also take any alternative suggestions.
Thanks.
No - it is not possible to add new layer modes but for including your own modes inside GIMP source code.
However, layers are a bit more generic now, since they can be written as a GEGL operation - I'd have to check the source, but all that is needed is probably to write the proper GEGL operation (which is easy to derive from the other layer modes), and add the new operation to the enums. The big drawback of this approach as compared to plug-ins is that you can't share the layer mode with other GIMP users, and even worse: the XCF files you create with your custom mode will only be "readable" in your modified copy of GIMP.
An workaround is to write a plug-in that creates a new layer from two underlying layers, combining them as you like. You'd have to invoke it manually each time you updated each layer. You'd have to use Python-fu, instead of script-fu,a s the later does not give one access to pixel values.
For the simple case you describe, though, it seems like a sequence of "alpha-to-selection",
"selection-to-channel", "copy", "add-layer-mask", "paste" can do what you want without a need to copy pixels around in a high level language.
I started writing some code for a 2D game, created a class "objets" trying to keep it as generic as possible. I have a few methods and attributes that are common to every kind of element (buldings, ppl, interface buttons, etc) like (w, h, x, y ...you know) but most of them only make sense when applied to and specific type of item.
So I would have to inherit a new class for every type of actor in the game?
Just wondering if this is a common practice, or maybe i should manage it in a different way.
Thanks in advance.
If you're introducing behaviour then subclass, however if the difference is attribute based then don't e.g.
Animal (has .colour and .makeSound) -> Dog (has .eatOwnPoop) -> RedDog (no, too specific, covered by colour)
Notice how I had ".makeSound" in Animal. I could have put .bark in dog, but then I'd have to put .meow in cat etc. The subclass can simply override and provide a concrete sound.
However, you can use interfaces to better cross-cut your code, but that's quite a lengthy topic and probably overkill for your needs (although it could help any unit testing you do).
It sounds like you are over-using inheritance. It is certainly a red flag when you simultaneously say "common attributes like ..." and "...only make sense when applied to a specific type." Also, it is a red flag that domain objects such as building share a common base class with an interface object like button. Finally, it is quite unusual to define your own objet (object?) class from which every class in your system derives. It's not inconceivable, but in combination with your other comments, it sounds like you've started down an unproductive path.
You might want to refer to a good tutorial on object-oriented design and analysis such as "Head First OOA&D"
You do not HAVE to do anything. Generally, it is useful to use derived classes if they exhibit some kind of commonality but become more specialised in nature requiring specific functionality at each level of inheritance. It is also good to use if you want to have polymorphic behaviour. You have asked a very open ended question but basically do not feel that you HAVE to use inheritance as not every problem requires it and indeed some people overuse inheritance, introducing it in places where it really is not needed. All in all, I would really recommend that if you haven't already that you read a good book on object oriented design as this will then get you to think about your code from a different perspective and greatly improve the way you view software and design it. It may sound like a cop out but this kind of question is very hard to answer without knowing all details of what you are doing.
I have an extremely hard time figurering out how classes needs to communicate with eachother. In a current project I am doing, many classes have become so deeprooted that I have begun to make Singletons and static fields to get around(from what I get this is a bad idea).
Its hard to express my problem and its like other programmers dont have this problem.
Here is a image of a part of the program:
Class diagram
ex1. When I create a Destination object it needs information from Infopanel. How to do that without making a static getter in InfoPanel?
ex2. DestinationRouting is used in everybranch. Do I really have to make it in starter and then pass it down in all the branches?
Not sure if this makes sense to anybody :)
Its a problem that is reacurring in every project.
After looking at your class diagram, I think you are applying a procedural mind set to an OO problem. Your singletons appear to contain all of the behavior which operate on the records in your domain model and the records have very little behavior.
In order to get a better understanding of your object model, I'd try and categorize the relationships (lines) in your class diagram as one of "is-a", "has-a", etc. so that you can better see what you have.
Destination needs some information from InfoPanel, but not likely all information. Is it possible to pass only the needed information to Destination instead of InfoPanel?
What state is being captured in the DestinationRouting class that forces it to be a singleton? Does that information belong elsewhere?
There's just too little information here. For example, I am not even sure if MapPanel and InfoPanel should be the way they are. I'd be tempted to give the decorator pattern a try for what it's worth. I don't know why a Listener is a child of a Panel either. We need to know what these objects are and what system this is.