I'm writing a small game. I have:
class MyGame
...
class_methods
a bit of game logic
end
# after my_game unwrapped code
putss
get.chomps
methods, loops (to be DRY)
interaction with user, returning values
Is there a correct approach to wrap code together? Is it correct to not wrap code after my_game class in any class or module, or should I always put my code in classes/modules?
I would wrap functionality in modules and classes, as there are some benefits to it:
a) you can easily write tests for code in classes (and for modules by including them in classes as mixins and testing the classes)
b) you have control over the visibility of functions/methods and you can actually create an interface in case you have a consumer of the game that needs to access something more than just the game class
c) it's easier to extend the functionality of parts of the game by creating new implementors of parts of the game's functionality
That said, there is no dogma on writing only in an Object Oriented way. In some cases (perhaps for scripts that will be used as command line scripts), just having some functions and code executing those functions might be enough (especially if the script is simple and short in general).
My advice regarding the structure of the little game you're building is to look for the interactions, the "verbs" that need to take place (ie the messages sent between objects) and then you'll come up with the classes that will send those messages (methods) and designing and structuring the game will get much easier I believe.
By the way, a good book that could help in the direction of designing software is the following:
http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330
Hope the above help.
Related
I've been reading Sandi Metz's Practical Object-Oriented Design in Ruby and many sites online discussing design in Ruby. Something I've had a hard time fully understanding is the proper way to implement dependency injection.
The internet is flooded with blog posts that explain how dependency injection works in what I think is a very partial way.
I understand that this is supposed to be bad:
class ThisClass
def initialize
#another_class = AnotherClass.new
end
end
While this is a solution:
class ThisClass
def initialize(another_class)
#another_class = another_class
end
end
And that I could send the AnotherClass.new like this:
this_class = ThisClass.new(AnotherClass.new)
That is the approach that Sandi Metz recommends at least. What I don't understand is where should a line like that go? It has to go somewhere and generally in examples of this what's shown is a line like that being placed totally outside of any class, method, or module as if I'm simply entering it all by hand in IRB for testing purposes.
This post (among others) suggests this different approach:
class ThisClass
def another_class
#another_class ||= AnotherClass.new
end
end
Jamis Buck would take a similar approach like this:
class AnotherClass
end
class ThisClass
def another_class_factory(class_name = AnotherClass)
class_name.new
end
end
However, these two examples both preserve AnotherClass's name inside ThisClass, which Sandi Metz says is one of the main things we're trying to avoid.
So what is the best practice for doing this? Should I make a 'dependency' module filled with methods that are factories for objects of each class in my application?
Something I've had a hard time fully understanding is the proper way to implement dependency injection.
I think the best definition of a "proper" implementation is one that adheres to the SOLID principles of object oriented design. In this case mostly the Dependency Inversion Principle.
In this regard, this is the only presented solution that does not violate the DIP(1):
class ThisClass
def initialize(another_class)
#another_class = another_class
end
end
In all other cases, ThisClass has a hard dependency on AnotherClass, and can not function without it. Furthermore, if we wish to replace AnotherClass with a third, we need to modify ThisClass, which is a violation of the Open Closed Principle.
Of course, in the example above, naming the parameter and instance variable another_class is not ideal, since we do not now (and do not need to know) what object is passed to us, as long as it responds to the expected interface. This is the beauty of polymorphism.
Consider the below example, taken from this ThoughtBot video on DIP:
class Copier
def initialize(reader, writer)
#reader = reader
#writer = writer
end
def copy
#writer.write(#reader.read_until_eof)
end
end
Here you can pass any reader and writer objects that respond to read_until_eof and write respectively. This gives you full freedom to compose your business logic using different pairs of read and write implementations, even at runtime:
Copier.new(KeyboardReader.new, Printer.new)
Copier.new(KeyboardReader.new, NetworkPrinter.new)
Which brings us to your next question.
It has to go somewhere and generally in examples of this what's shown is a line like that being placed totally outside of any class, method, or module [...]
You are correct. While object thinking involves modelling the domain with well isolated, decoupled, and composable objects, you will still need to define how these objects interact, in order to implement any business logic. After all, having composable objects is no good unless we compose them.
The analogy that is often made here is to think of your objects as actors. You are the director, and you still need to create a script(2) for the actors to know how to interact with each other.
That is, you need an entry point into your application. A place where the script starts. This might itself be an object--normally an abstract one. In a command line application, it can be your classic Main class, and in a Rails application it can be your controller.
This might seem strange at first, because the focus of object thinking is on modelling concrete domain objects, and a great deal of all writings on the subject is dedicated to this effort, but just remember the actor-script metaphor, and you'll be on your way.
I strongly recommend you pick up the book Object Thinking. It does a great job explaining the mindset behind object oriented design, without which knowing the language specific implementation details becomes rather futile.
(1): It is worth noting that some proponents consider storing an instance of another class in an instance variable an anti-pattern, but in Ruby, this is fairly idiomatic.
(2): I am not sure if this is the origin of the term script in programming in general, but maybe some historian can shed some light on this.
Pertaining to Ruby, can someone state the relationship between Class, Objects, and Methods in layman's terms? And maybe even give an analogy?
New to OOP and trying to grasp the concept.
note: OOP is independent of Ruby.
Classes are like recipes.
Objects are the actual food you prepare from a recipe.
Methods are ... don't really fit in this metaphor. But they are the behaviors an object can perform. Some might say methods are the messages an object will respond to.
A friend gave me this analogy:
"It's like a watch. The Class is the watch casing, it encompasses the inner workings of the watch (Objects and Methods). The hands are the Objects, they perform the function of the watch based on the movement of the gears (Methods). The gears and springs underneath the face are the Methods; they are the heart of the watch that make up the function of the hands (Objects). Without the gears (Methods) the hands (Objects) have no function. Without either of those, there's no need for the watch casing (Class) to exist."
Classes are your blueprints
Methods are your tools (to build, to modify, to adjust)
Objects are your buildings
Remember that your objects are your nouns (e.g. a building) ... methods are you verbs (e.g. is built)!!
I just found web2py a couple days ago, and have been reading the documentation and through the source of a few example applications. I want to start programming more in Python. It seems that my take on MVC is a little skewed from theirs [web2py community].
After learning and working with PHP (and the Kohana framework), I'm used to the thin controller - fat model principle, where all business logic is placed in the model and the controller does nothing more than delegate what methods to perform on the model, and then passes data onto the view for rendering. However, it seems that 99% of the applications I've seen for web2py have fat controllers (putting all business logic in the actions), and the models are nothing more than table/constraint definitions.
I'm pretty well set on my view of a model, and I would rather put the business logic in the models (for re-usability and DRY code) but I haven't seen any code online that does this, although, to be fair, I haven't found an ample amount of applications. Can somebody point me in the right direction.
To be clear, I would like to make my models actual classes and encapsulate all business logic and database interactions into explicit methods. Something along the lines of...
class Article(object):
def get_article(self, id):
# Retrieve article by id, using db instance
pass
def get_latest_articles(self, limit):
# Retrieve latest articles
pass
def get_hot_articles(self, limit):
# Retrieve hot articles, based on algorithm for "hot"
pass
def create_article(self, data):
# Insert article
pass
def define_tables(self):
# Define schema the web2py way
pass
I haven't found the right way to do this.
I'm not very well rehearsed on web2py, but I know there are a lot of features. The DAL, for instance, seems to be a very powerful feature which is tightly integrated with other helpers. I wonder if splitting my business logic as stated above would limit any of these features?
I think part of the difference is that web2py uses a DAL (database abstraction layer) rather than an ORM. You might find this explanation helpful. As it points out, in some cases, computed fields or virtual fields may do what you want. Also, some of the methods defined in your example class would be quite simple DAL statements and would probably not be worth writing methods for.
Of course, if you want, you can define classes and functions in your models (or modules) and simply call them from your controllers -- whatever works best for you.
I'd like to know when is the best time to use mixins vs calling a method directly.
For example, consider HTTParty. On one of its examples https://github.com/jnunemaker/httparty/blob/master/examples/basic.rb
you can use HTTParty.get('http://twitter.com/statuses/public_timeline.json') or you can create a class that includes HTTParty and then use it as you would calling HTTParty itself.
What's the difference with me just creating something like this:
class Partay
#base_uri = 'http://localhost:3000'
def self.post(endpoint, options)
HTTParty.post(#base_uri + endpoint, options)
end
end
versus the given example:
class Partay
include HTTParty
base_uri 'http://localhost:3000'
end
True that in such a trivial example perhaps using the include would save more characters, but I'd imagine on a much more complicated class it doesn't really make a difference.
A few clarificatory questions:
Would this be related to a composition vs aggregation argument? Is there any design or architecture best practice regarding this? Should I treat mixins as some sort of inheritance and use them as such (inheritance if it's an is-a relationship, composition if it's a has-a relationship, etc.)? Should I only mixin a module if it was intended to be done so (because docs say it expects certain methods from you, like Enumerable) or is it just good practice to do so? Would using a mixin mean a tighter coupling between the module and my class (and is it relatively good or bad in general)?
In the given example, there is not much difference, other than the syntax is much more friendly with the mixin, and could potentially become a DSL that you can use later.
More generally, mixins allow you to use these same functions in different classes without repeating yourself, and without extending another class (mixins are, for example, a way of working around the fact that ruby does not allow multiple inheritance). This favours reuse and goes towards the DRY philosophy dear to the ruby users. As ruby is duck-typed, mixins allows you to take full advantage of polymorphism without inheritance.
Another great advantage of mixins is that they can be added at runtime, so this means you can add behaviour to a class "dynamically".
Update: I personally prefer using modules as mixins, rather than calling methods on it as the methods then become part of your class, which means that they can access the other members of the class. I’m however reluctant to call it a is-a relationship, even though that’s what it is in practice. As the “Well-Grounded Rubyist” says, classes model entities or things (class names tend to be nouns), modules encapsulate properties or characteristics (module names tend to be adjectives).
I'm reading through the (still beta) rspec book by the prag progs as I'm interested in behavioral testing on objects. From what I've gleaned so far (caveat: after only reading for 30 min), the basic idea is that I want ensure my object behaves as expected 'externally' i.e. in its output and in relation to other objects.
Is it true then that I should just be black box testing my object to ensure the proper output/interaction with other objects?
This may be completely wrong, but given all of the focus on how my object behaves in the system, it seems this is ideology one would take. If that's so, how do we focus on the implementation of an object? How do I test that my private method is doing what I want it to do for all different types of input?
I suppose this question is maybe valid for all types of testing?? I'm still fairly new to TDD and BDD.
If you want to understand BDD better, try thinking about it without using the word "test".
Instead of writing a test, you're going to write an example of how you can use your class (and you can't use it except through public methods). You're going to show why your class is valuable to other classes. You're defining the scope of your class's responsibilities, while showing (through mocks) what responsibilities are delegated elsewhere.
At the same time, you can question whether the responsibilities are appropriate, and tune the methods on your class to be as intuitively usable as possible. You're looking for code which is easy to understand and use, rather than code which is easy to write.
If you can think in terms of examples and providing value through behaviour, you'll create code that's easy to use, with examples and descriptions that other people can follow. You'll make your code safe and easy to change. If you think about testing, you'll pin it down so that nobody can break it. You'll make it hard to change.
If it's complex enough that there are internal methods you really want to test separately, break them out into another class then show why that class is valuable and what it does for the class that uses it.
Hope this helps!
I think there are two issues here.
One is that from the BDD perspective, you are typically testing at a higher level than from the TDD perspective. So your BDD tests will assert a bigger piece of functionality than your TDD tests and should always be "black box" tests.
The second is that if you feel the need to test private methods, even at the unit test level, that could be a code smell that your code is violating the Single Responsibilty Principle
and should be refactored so that the methods you care about can be tested as public methods of a different class. Michael Feathers gave an interesting talk about this recently called "The Deep Synergy Between Testability and Good Design."
Yes, focus on the exposed functionality of the class. Private methods are just part of a public function you will test. This point is a bit controversial, but in my opinion it should be enough to test the public functionality of a class (everything else also violates the OOP principle).