I'm still new to OOP, and the way I initially perceived it was to throw alot of procedural looking code inside of objects, and think I'd done my job. But as I've spent the last few weeks doing alot of thinking, reading, and coding (and looking at good code, which is a hugely under-rated resource), I believe I'm starting to grasp the different outlook. It's really just a matter of clarity, simplicity, and organization once you get down to it.
But now I'm starting to look at things as objects that are not as black and white a slamdunk case for being an object. For example, I have a parser, and usually the parser returns some strings that I have to deal with. But it has one specialized case where it has to return an array, and what goes in that array and how it's formatted has specialized rules. This only amounts to two lines plus one method of code, but this code sticks out to me as not being cleanly fitting in the Parser class, and I want to turn it into its own "ActionArray" object.
But is it going to far? Has OOP become a hammer that is making me look at everything like a nail? Is it possible to go too far with turning things into objects?
It's your call, but you should think of objects as real life objects.
Take for example a car. You could describe a car with different objects:
Engine
Wheels
Chassis
Or you could describe a car with just one object:
Engine
You can keep it simple and stupid or you can spread the dependency to different objects.
As a general guideline, I think Sesame Street says it best: you need an new object when "one of these things is not like the others".
Listen to your code. If it is telling you that your objects are becoming polluted with non-essential state and behavior (and thus violating the "Single Responsibility Principle"), or that one part of your object has a rate of change that is different from the rest, and so on, it is telling you that you are missing an object.
Do the simplest thing that could possibly work. When that no longer works, do the next simplest thing. And so on. In general, this means that a system tends to move from fewer, larger objects to more, smaller objects; but not always.
There are a number of great resources for OO design. In addition to the ones already mentioned, I highly recommend Smalltalk Best Practice Patterns and Implementation Patterns by Kent Beck. They use Smalltalk and Java examples, respectively, but I find the principles translate quite well to other OO languages.
Design patterns are your friend. A class rarely exists in a vacuum. It interacts with other classes, and the mechanisms by which your classes are coupled together is going to directly affect your ability to modify your code in the future. With poor class design, a change that you make in one class may ripple down and force changes in other classes, which cause you to have to change other classes, etc.
Design patterns force you to think about how classes relate to each other. For example, your Parser class might choose to implement the Strategy design pattern to abstract out the mechanism for parsing. You might decide to create your Parser as a Template design pattern, and then have each actual instance of the Parser complete the template.
The original book on Design Patters (Design Patterns: Elements of Reusable Object-Oriented Software is excellent, but can be dense and intimidating reading if you are new to OOP. A more accessible book (and specific to Ruby) might be Design Patterns in Ruby, which has a nice introduction to design patterns, and talks about the Ruby way of implementing those patterns.
Object oriented programming is a pretty tricky tool. Many people today are getting into the same conflict, by forgetting the fundamental OOP purpose, which is improving code maintainability.
You can always brainstorm about your future OO code reusability and maintainability, and decide yourself if it's the best way to go. Take look at this interesting study:
Potok, Thomas; Mladen Vouk, Andy Rindos (1999). "Productivity Analysis of Object-Oriented Software Developed in a Commercial Environment"
Related
Actually sometimes you are required to write some custom code to achieve some functionality, there would be 2 possible approaches there:
make your implementation by joining already given methods of
Objective-c
write your custom code
At that point I am confused which code base is better(in performance), that can only be decided if I luckily find Time-Complexity of Objective-c methods. So is there any way to know about it?
There are a lot of methods and functions you can call in the SDKs for iOS (and other Apple platforms), so this question is perhaps excessively broad.
But a discussion of time complexity is usually about algorithmic complexity, so we can restrict our scope to those calls that are the building blocks of algorithms where we measure time as a function of input size — that is, things like collection operations rather than, say, UIApplication registerForRemoteNotifications.
By and large, however, Apple doesn't talk much about the computational complexity of the high-level data structures in Cocoa. This probably has something do with Cocoa's design goals being strongly in favor of encapsulation, with simple interfaces hiding powerful, dynamic, and possibly adaptable implementations. Examining CoreFoundation — the open source implementations underlying the central bits of Cocoa, like collections — bears this out. Here's a great writeup on how NSArray is sometimes O(1) and sometimes not.
There's certainly something to be said for a philosophy where you're not supposed to care about the complexity of the tools you're using — tell it what you want to do, not how you want it done, and let it optimize performance for you, because it can second-guess you better than you can second-guess yourself. It goes well with a philosophy of avoiding premature optimization.
On the other hand, there's also some sense to a philosophy of having basic building blocks of enforced, predictable complexity so that you can more easily plan the complexity of the algorithms you build from them. Just to show that Apple seems to do it both ways, it appears this is the philosophy of choice for the Swift standard library.
I've been studying Ruby on Rails for a class project. I keep hearing "everything in Ruby is an object". What I am not sure I understand is WHY that is a good thing, or maybe IF that is a good thing?
A counterexample would be that in Java Integer is an object but int is not, which means different operations apply to both (admittedly in recent Java there is automatic conversion to/from the object version, but this can introduce unexpected performance issues). Objects are a little slower due to indirection, but more flexible; everything being an object means everything behaves consistently. Again Java would be an example: an array is not an object, and ArrayIterator is something that is bolted on after the fact (with multiple third party implementations, even) and therefore not quite consistent with the way collection class iterators work.
It makes Ruby very flexible. Numbers and other primitive types can be altered or extended.
This can also result in quite elegant syntax:
5.times { print "print this 5 times" }
Everything in Ruby is not an object (Yes, I know what people generally mean when saying that statement, but its still not totally true). It is more appropriate to say "everything in Ruby evaluates to an object". This is an interesting insight to make, and for the more proper elaboration, I'll simply cite David Black. It's a good read:
http://rubylearning.com/blog/2010/09/27/almost-everything-is-an-object-and-everything-is-almost-an-object/
Like other people have pointed out already, there are primitives other than objects in other languages like Java. For the compiler and computer, it's a good thing to get the most efficient code, however, programmers need to use different functions and methods based on which one they are dealing with.
Since Ruby is designed for humans, not computers, sacrificing a bit of computational resource for the sake of human's productivity is considered good. Thus, Ruby has never had the distinction between objects and primitives. It definitely lowers the learning curve for novices, too. Internally, Ruby is using a technique called tagged pointers and the performance penalty by the lack of primitives is not as bad, as far as I know.
Another thing worth noting is that in Ruby, classes are also objects, which means you can modify classes and their behaviors with ease even when the code is running. This dynamic nature gives programmers so much power and the Ruby code tends to look quite terse. Ruby on Rails is taking full advantage of this dynamic aspect of the Ruby language.
At one point while traveling the web, I came across a great page which contrasted the clarity and terseness of different methods of doing a sequence of operations without having to make a bunch of throwaway variables, e.g., Var1, Var2, Var3. It tried list comprehensions, folds, maps, etc. For some reason, now matter what I google, I can't find it again. Anyone have any idea what I'm talking about? Or want to explore the topic anyway?
Your question doesn't make much sense.
List comprehensions, fold, and map aren't for avoiding variables (nor are they interchangeable), they're the right ways to process data depending on what you're trying to do.
This is the article you were looking for:
http://erlanganswers.com/web/mcedemo/VersionedVariables.html
It is probably more of an art than a science. In a nutshell my advice is to lean away from using throw-aways as a general habit, but equally, do not be afraid of using them intelligently and sparingly where you feel appropriate or necessary.
When you are starting to learn then by all means use throw-away variables if it helps you break things down into understandable chunks. But try to break away from that sooner rather than later, as using throw-aways may at times make your code harder to maintain and modify. On the other hand, even when you are experienced you may sometimes find that it is worth using throwaways for the same reason : keep things readable and manageable for less experienced programmers. Purists may say that you should never use them, but I believe that when you consider the lifetime costs of software maintenance it is important to remember that readability is very important. Maybe this argument doesn't apply if you are lucky enough to work in an environment that only hires the best of the best, but for the rest of us that's simply not a reflection of the real world.
The bottom line : what is "right" depends on your skill level, the skill level of your peers, what you are doing, and the likely volatility, complexity, and lifetime of the code. Use your best judgement.
In response to the answer saying the question doesn't make sense, you would certainly think it made sense if you saw the article to which I'm referring. The point is to elegantly process a series of statements without redundant intermediate variables. Zed is right on target. I really wish I could find the original link because it was super detailed and went through 5 or 6 methods, some of which were referenced from the erlang mailing list, and weighed the pros and cons of each.
So DRYing up code is supposed to be good thing right? There was a situation in one of the projects I was working on where there were certain models/entities that were more-or-less the same except the context in which they were being used. That is, Every such entity had a title, descriptions, tags, a user_id etc and some other attributes. Hence their CRUD actions in their respective controller looked pretty similar.
My manager argued that its repetition of code and needs to be DRYed up. Hence he came up with CRUD ruby module that when included took care of CRUD actions for the controllers of all these entities. But eventually, Simplicity was compromised. The code lost readability as every "thing" was named "object". Debugging became difficult and the whole point of DRYing up the code was lost.
This was just one case. There are several of them where DRYing up resulted in complex, hard-to-debug code. So the question is, when do we stop DRYing up the code? Because not every time you realize the code has lost simplicity (And often the code author never realizes the simplicity of code is lost). Also, if we have to choose between simplicity and DRYed code, what should choose, if at all there comes a situation where you could get only either of them.
From what I understand, if DRYing up code is causing loss of simplicity, we are doing something terribly wrong. I think, we should be DRYing up code that is repeated and has single responsibility. If the code responsibilities are different and/or the abstraction of entities cannot be named, we are not repeating code. The code pattern might be repeated but its a different code altogether with a responsibilty of its own. If DRYing is resulting into vague code, you are probably trying to DRY up code with different responsibilities that have a similar pattern which is not really a good practice. DRYing should enhance the simplicity, not suppress it.
If you are following REST, then yes, the controllers will be very similar and largely boilerplate. I agree with your manager that it's a problem.
It sounds though like he came up with a suboptimal solution. For a better one, check out Jose Valim's inherited_resources plugin that is being incorporated into Rails 3.
Readability and Maintainability are the two most important features of good code. Unfortunately, a compromise has to be made sometimes. It's a balance question and not everyone is going to agree.
Myself, I lean towards your point of view as well. I would rather have some apparent repetition if it means the code is easier to understand.
As for the 'debugging' problem, I am in the habit when I create such a 'base class' to include a supplementary field. This field is a simple string which identify the most derived class (and is thus passed from Constructor to Constructor). Then each message is going to print this field + the object id "realtype[id]" and everything is suddenly much easier to debug.
Now on to DRY.
There are two things to DRY:
building a hierarchy
using generic code
The first point should now be well understood. A hierarchy of class means a IS-A relationship. If two classes have similar behavior but are otherwise functionally unrelated, then they SHOULD NOT be part of the same hierarchy. It only confuses the poor maintainer and hurts readability.
The second point can be used much more often, especially with scripting languages. For the precedent example, I would argue that instead of having a hierarchy of classes, you could simply define generic methods that would take different classes (modeling different business) and treat them uniformly. This way you avoid repetition (DRY) yet you do not sacrifice readability (imho).
My 2 cts.
If someone every told me--with a straight face--that my code needed DRYing, I would probably take that as a sign that anything else they were going to do was going to be really far-fetched and for-the-sake-of-it.
That having been said, there is also a difference between simplicity in writing code (laziness) and simplicity in the code itself (elegance). I agree, though, that there is a balance. I had this situation myself one particular time (in PHP, but oh how it reminds me of your dilemma):
$checked = ($somevariable) ? "checked=\"checked\"" :"";
echo "<input type="radio" $disabled_checked />";
$checked = ($someothervariable) ? "checked=\"checked\"" :"";
echo "<input type="radio" $checked />";
This isn't even a very good example of what I was dealing with. Essentially, because it's a radio input, both inputs needed a some way of knowing which was to be bubbled in. I knew it had what your boss might call "wetness" issues, so I racked my head trying to come up with some solution that would be graceful and to the point. Finally I showed it to a senior developer and he said "No, it's all in order, it does what it needs to. It's only one extra line."
I felt a relief at being reminded that I was hurting my project more then helping by worrying over this, but at the same time, I'm still disappointed that he was so casual about a fundamental principle (as though it wasn't one of his, though I'm sure it is).
So while I agree, your manager probably was doing something just for the sake of doing it, it is only when we strive to come up with the better methods and approaches that we get better languages like Ruby and Python and cooler libraries like Jquery.
Basically, what if next week you suddenly had 70 things instead of 2? If your boss's objects make that a snap, he was right. If it's the same amount of trouble (in the code or in the execution), he was wrong. But that doesn't mean there isn't a better answer then keeping it simple because it's only a couple of things.
The aim of the DRY principle is to help increase the "quality" of the code.
If the changes aren't improving the quality of the code, it is time to stop.
The ability to judge this comes with experience. As requirements change, the most appropriate way to refactor the code also changes, so it's impossible to have everything ideal - at least you need to freeze the requirements first.
Minimising the size of the code should generally not be a consideration in the quality unless you are codegolfing, so don't DRY when the only purpose is to reduce the size of the code.
Complicated tricks can do more harm than good.
A key reason for applying DRY to improve maintainability is to ensure that when a code change is necessary, that change only needs to be made in one place, thus avoiding the risk that it doesn't get changed everywhere that needs it.
But I'm not telling the whole story:
This interview with Dave Thomas has DT saying:
DRY says that every piece of system
knowledge should have one
authoritative, unambiguous
representation.
The first time I saw "DRY" was in The Pragmatic Programmer so I'm inclined to go with Dave on this.
There's another article worth reading here
But DRY is a principle, not a rule: the better we understand the principle, the more able we should be to recognise situations where it should be applied.
(And finally, I think I'd want a little more than "more-or-less the same" before I started "DRY"ing that code: if I could see a clear way in which the two things might diverge in the future then I'd be inclined to leave them alone).
For me, duplicated code is a smell that can have multiple origins:
Missing variables (introduce variable).
Missing methods (push expression into a method).
Feature envy (push behaviour down into the envied class).
Over-generalization (break up generic class into specific concrete classes).
Insufficient abstraction (push attributes and behaviour down into new class).
This list is probably incomplete. Consider it a starting point.
When you find duplication, think about what problem it's symptomatic of. Then take a stab at addressing that problem. When you're done, consider the readability of the new code. If it has deteriorated, you may be in one of these positions:
You misidentified the problem at the root of the duplication (revert, rethink, try again).
The duplication is a necessary trade-off (revert your change and live with it).
Your software is necessarily complex (commit your change and live with it).
Consider posting example code along with questions like this, if possible. They provide something concrete to work around. And remember, a lot of this stuff is very subjective.
If you're writing something by yourself, whether to practice, solve a personal problem, or just for entertainment, is it ok, once in a while, to have a public field? Maybe?
Let me give you an analogy.
I come from a part of the world where English is not the primary language. But it’s necessary for all things in life.
During one of those usual days during my pre-teen years I said something very funny in English. Then my Dad said, “Son, think in English. Then you’ll get fluent”
I think it applies perfectly to this situation.
Think,try and question best practices in your playground. You will soon realize what’s best for what.Why are properties needed in the first place. Why should this be public? Why should I not call a virtual member from the constructor? Let me try using "new" modifier for a method call. What happens when I write 10 nested levels of if-then-else and try reading it again after 10 days. Why the heck should I use a factory pattern for a simple project. Et cetera.
And then you’ll realize without shooting at your foot, why design patterns are patterns...
I think it's reasonable if you're consciously throwing the code away afterwards. In particular, if you're experimenting with something completely different, taking shortcuts makes sense. Just don't let it lead to habits which cross over into "real" code.
Violating general principles is always "ok"! It is not an error to violate a principle but it is a trade off. The cost of not writing clean code will be higher the longer your software will survive. My take on this is: If in doubt make it clean!
Of course it's OK. It's your code, you can do whatever you want with it. Personally, I try to stick to good practice also in my private code, just to make it a natural habit so I don't have to think about it.
The short answer is yes, if you believe that you're gaining a lot by making things public instead of private with accessors you are welcome to do so. Consistency, I think, is the biggest thing to keep in mind. For instance, don't make some variables straight public, and some not. Do the same across the board if you break with best practices. It comes back to a trade-off. Almost no-one follows many of the IEEE specs for how Software Engineering should be executed and documented because the overhead is far too great, and it can get unmanageable. The same is true for personal, light-weight programming. It's okay to do something quick and dirty, just do not get used to it.
Public members are acceptable in the Data Transfer Object design patter:
Typically, the members in the Transfer Object are defined as public, thus eliminating the need for get and set methods.
One of the key advantages of OOP is for scaling and maintainability. By encapsulating code, one can hide the implementation. This means other programmers don't have to know the implementation, and can't change your object's internal state. If you language doesn't support properties, you end up with a lot of code which obfuscates and bloats your project. If the code doesn't need to be worked on by multiple programmers, you aren't producing a reusable component, and YOU are the maintenance programmer, then code in whatever manner allows you to get things done.
Does a maid need to make his/her own bed in the morning in order to practice properly making a bed?
Side note: it also depends on the language:
In Scala, according to the Uniform Access Principle, clients read and write field values as if they are publicly accessible, even though in some case they are actually calling methods. The maintainer of the class has the freedom to change the implementation without forcing users to make code changes.
Scala keeps field and method names in the same namespace.
Many languages, like Java, keep field and method names in separate namespaces.
However, these languages can’t support the uniform access principle as a result, unless they build in ad hoc support in their grammars or compilers.
So the real question is:
What service are you exposing (here by having a public field)?.
If the service (get/set a given type value) makes sense for your API, then the "shortcut" is legitimate.
As long as you encapsulate that field eventually, is it ok because you made the shortcut for the "right" reason (API and service exposure), versus the "wrong" reason (quick ad-hoc access).
A good unit test (thinking like the user of your API) can help you check if that field should be accessed directly or if it is only useful for internal development of other classes within your program.
Here's my take on it:
I'd advise avoiding public fields. They have a nasty habit of biting you later on because you can't control them. (The word you're looking for here is volatility.) Further, if you decide to change their internal implementation, you have to touch a lot more code.
Then again, that's what refactoring tools are for. If you have a decent refactoring tool, that's not nearly so difficult.
There is no silver bullet. I can't repeat this enough. If you have work to do, and you need to get it done in a hurry, writing one line of code instead of eight (as is the case in Visual Basic) is certainly faster.
Rules were meant to be broken. If a rule doesn't necessarily apply in your case, don't use it. Design patterns, coding guidelines, laws and best practices should not be treated as a straightjacket that requires you to needlessly complicate your code to the point where it is enormously complex and difficult to understand and maintain. Don't let someone force you into a practice just because it's popular or "standard" when it doesn't fit your requirements.
Again, this is a subjective opinion, and your mileage may vary.