I just want to have other opinions about this one that I have been debating in my head, for example I have class user_controller, and class user
class User
attr_accessor :name, :username
end
class UserController
// do something about anything about users
end
The question would be should I have logic in my User class so it would be
user = User.new
user.do_something(user1)
or it should be
user_controller = UserController.new
user_controller.do_something(user1, user2)
I'm not sure which one is the best design, I personally quite like the first one so for example it would read like
john = User.new
john.accept_friend(jane)
instead of
user_controller = UserController.new
user_controller.accept_friend(john, jane)
What are pros and cons of those patterns? This is not just specific to Ruby, it's because I thing ruby is easier in typing.
Edit: There is really good conversion going on, but I quite like to here more from people. Thanks everyone.
Yes, you should keep logic in your model! That is, if you do actual object oriented programming (and it looks like you do). To quote Wikipedia:
Object-oriented programming (OOP) is a programming paradigm using
"objects" – data structures consisting of data fields and methods
together with their interactions – to design applications and computer
programs.
This is especially true if you're trying to do domain driven design (which your tags imply). DDD is all about expressing your domain with objects.
Martin Fowler says putting the logic outside your model is an anti-pattern.
Most people would say that you should not keep logic in your model-classes. Exceptions might include:
helper functions accessing a contained Collection (addToList(Object o), getFromList(int index), etc etc)
Standard Object and similar overrides (equals, hashCode, toString, clone, compareTo, etc)
Data pre/post processing (like fixing strings to uppercase or stuff like that)
Since people won't expect there to be logic in model classes, you should probably avoid it too. It will confuse other developers who might have to look at and maintain your code in the future. After all, that is why there are patterns - to help other developers recognize and maintain your code.
I believe the first one is better, you have a model and a class that has all the information needed to operate that model and that model might need some other information to do some operations.
try reading more about Information Expert.
In such scenarios, the trade off should be considered.
It is good to add accept_friend in the user class if you are sure that the user class will not grow in size going forward.
On the other hand, it is preferred to move accept_friend into service classes like UserController in following scenarios.
To avoid user class grow in size. Such logics can be moved to these subclasses(Usercontroller) thus making the classes look simple
For resuability . Tomorrow if there is a class called superuser which also needs accept_friend functionality, then UserController class can be resued like
user_controller = UserController.new
user_controller.accept_friend(Superuser1, Superuser2)
Related
Some class names are so "generic" that they are often found in several different packages, including in libraries and application code. Some examples:
Comment
Component
Factory
Location
Region
In my IDE, attempting to auto-complete the import for a class like one of these summons several competing suggestions.
When naming classes, is it a good idea to avoid class names already used elsewhere?
For some of these examples, I would imagine that using such class name is discouraged because it is simply not meaningful enough (e.g. Factory), but I am wondering whether it is discouraged to use a class name because it is used (frequently) elsewhere.
You should use class names where they make the most sense for you. None of the names above that you've proposed are off limits, and there's no reason why you can't use them (assuming a language that supports namespaces and can avoid naming conflicts in this way).
However, you may consider drilling down to class names that are more specific and precise, which will better describe the meaning of the objects in your code. For example:
Instead of Comment: LineComment or BreakComment could easily be class names in a compiler project where you would like to create semantic blocks for comments.
Instead of Component: ListComponent, CalendarComponent, or ViewComponent make particular sense when implementing a UI library where you have class-based components.
Instead of Factory: PizzaFactory makes more sense if you're trying to make pizzas!
Instead of Location: GeographicLocation or SemanticLocation makes more sense when implementing a directions based navigation app, and you're trying to distinguish between '45 deg N, 77 deg W' and 'next to the pizza place'.
Region: CodeRegion could be used in a compiler, and GeographicRegion could be used in a Maps app.
If you're afraid to be specific, namespaces and packages help. However, there is nothing discouraging you from using the same name for a class as another package where it makes sense. The class names specifically aren't copyrighted, and most IDEs now are smart enough to make distinctions between what packages you're referring to when using autocompletion.
For the most part, specificity is helpful in assisting other developers to read your code, which every developer can appreciate!
Comment, Region, and Location seem fine. Personally, so subjectively, Component and Factory are definitely too common to use but objectively I can't think of any conventional reason not to use them as names. I'd definitely try and couple those names with their respective usage, for example; TaskFactory, WidgetComponent, ButtonFactory, etc.
Depends if we are talking about business or technical part.
In technical part: using common names is actually a way to let others know about the patterns used, Factory is a good example - when you see a class named like SomethingFactory, you can expect a Factory Pattern. It goes further to frameworks, libraries etc. - SomethingAutoConfiguration with Spring-Boot, SomethingEntity with JPA, I think with frontend frameworks (React, Angular) Component is a really common word. So ye, by all means, use them, as long as you use them correctly.
In business part: simple, if those words describe your business domain, then by all means use them. Don't try to invent some fancy names (or thesaurus!) just because the words seem common, it's your business domain - it's sacred.
So I have this container class called ShipStorage which store objects in an array. I have another class called FileManager which uses the object of ShipStorage. My professor said container classes should not be inputting or outputting(i think that means cannot use System.out.println). Will FileManager be considered a container class as well when it only uses the ShipStorage obj?
My professor said container classes should not be inputting or outputting.
There is a general principle in OO design called Separation of Concerns. A class should do things that are its "concern" and not do things that are not its "concern".
(A dishwasher washes dishes. Heating microwave dinners is not its concern.)
In the design that you are implementing, the purpose of a container class is to contain objects. Inputting or outputting the objects is not its concern. That is (presumably) the concern of the FileManager class, or some other class.
This is a reasonable design decision for your teacher to make, and probably how I would design it too. Either way, this is what your teacher has said to do; i.e. the "requirements". Therefore, it is how your code should work.
(i think that means cannot use System.out.println)
That is an example of the things that your container should not do ... in this project.
The Java programming language doesn't insist that applications are designed properly, but as you get more experience you will find that good design has many benefits, especially when you are dealing with complicated applications.
Is it ok to use empty interfaces for object modeling?
E.g. the following interface extends other empty interfaces in order the characterize the object 'Ferry':
public interface Ferry extends Watercraft, StationBased, Scheduled, Oneway, Motorized {}
Watercraft, StationBased, etc., are all empty interfaces, too, so they kind of act as a marker. However, they are not used by the JVM or compiler. These classes are only used for modeling purposes.
Is this good practice? Should an interface not usually provide some kind of common functionality, and not merely mark a class?
Yes, you can use empty interfaces for object modeling, but... Object modeling without any use-case is IMO overstretching it.
You write code to execute concrete actions, you model it to leverage general abstractions in the domain, and yes you can over-abstract your code.
Adding an interface in code is a classification or typification, which is only necessary as long as there is a taker for it. Otherwise it is plain dead code.
My worst encounter which sometimes still haunts me in my nightmares was an abstraction over business services, which essentially replaced it with a single method taking a map as arguments and returning an object which either contained the result or an error state. Effectively modeling a method invocation, but this time without types. Having forced this down on all business methods was simply a nightmare to unravel later.
There is nothing wrong with doing it that way except that you may discover quite quickly that changing the structure or adding new forms will become unpleasant.
I would probably consider a much more flexible enum option.
enum CraftAttributes {
Watercraft,
StationBased,
Scheduled,
Oneway,
Motorized;
}
class Ferry {
Set<CraftAttributes> attributes = EnumSet.of(
CraftAttributes.Watercraft
//...
);
}
There are lots of sweet thing you can do with unions and intersections of Sets that make for powerful but lucid code.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I’m having trouble understanding how classes relate to their methods. Is a method something that the object does, or something that’s done to it? Or is this a different concept entirely?
Specifically, in a library’s software system, should the borrow() method belong to the class representing the library patron, or the class representing the item that the patron is borrowing? My intuition is that it should read like patron.borrow(copy), like English sentence structure, subject.verb(object); but my instructor says that’s Wrong, and I don’t understand why he would have borrow() belong to the Copy class (and he doesn’t really explain things too well). I’m not looking for justification, but can someone just explain the proper relationship?
Edit: This question was closed as “off topic”. I don’t understand. Are software design questions not appropriate for this site?
subjective :) but honestly, I'd go with the Information Expert Pattern and say something like
library.lend(item, patron)
The library contains the information about the items it has (perhaps in its catalog).
The library lends the item to the patron (which it knows because it registers them)
Not sure how your instructor sees this, but this is the level of 'abstraction' (software objects mimicking real world entities) that would make sense for your scenario.
You should not confuse the idea of OOP with one specific incarnation like Java or C++.
This limit "methods are a property of the object" is not part of the OOP idea, but just of some implementations and as you discovered it doesn't scale well.
How many methods sould an "integer number" object have? What is more logical... myfile.write(myint) or myint.write(myfile)? There is really no good general answer to this. The idea of a method being part of a single object is a special case and sometimes the bending needed to fit the problem to this solution can become noticeable or even close to a showstopper. The answer is really totally acceptable only when a method has no parameters except the object being processed: single dispatch is a perfect answer only when there is a single type involved.
In other languages you have a separation between objects and methods, so for example you have the file object, the integer object and a method write(myfile, myint) that describes what to do when the operation is needed... and this method is neither part of the file nor of the integer.
Some generic words first.
Software construction is not something which should be governed by English language rules or "beauty" or whatever, it's engineering discipline. Think of whether your design solves the problem, whether it will be maintainable, whether it will be testable, whether it will be possible to parallelize development and so on. If you want something more formalized take a look at the "On the Criteria To Be Used in Decomposing Systems into Modules" by D. L. Parnas.
As for your library example. Imagine you have a Copy outside of library, shoult it have borrow method then? How the borrowing is registered? Are you ok with either Copy or Patron classes responsible for data storage? It looks more appropriate to put borrow into a Library class. Responsibilities will be clearly divided, you wouldn't need to know much about borrowing to implement Copy and Patron and you wouldn't need much details about them to implement Library.
Public methods exposed from a class are the tasks that can be performed on the entity.
That way the class would only encapsulate its behavior.
For example:
if i say
Computer.TurnOn()
The method will only work on the computer system.
instead if i say,
SomeOne.TurnonComputer()
The someone will now have the responsibility to turn on the computer(set related properties of computer), that means we are not meeting the concept of encapsulation and scattering the class's properties all over the place.
As #Ryan Fernandes said, the lend/borrow operation cannot be with either patron or book. It has to be with some class that knows about the status of all the books and patrons of the library. For e.g., are there pending reservations against a book? How many copies are available? Has this patron paid all the fees? Is he eligible for this book? So typically this should be in Library or a LibraryService class.
The point of OOP is to create polymorphic functions that, in each implementation, deal with a defined set of data which obey specific invariants.
It follows that a method which alters an object should be defined in the class of that object. It matters less where code that is purely functional lives, but it should probably live on the type of its input (if it takes a single input) or on its output.
In your example, if borrow alters data in copy, then it should live there. If, however, you model the loan status of a book by it being held in a particular collection (either in a patron, or in a collection for the library), it would make more sense to put borrow on the holder classes. That latter design, however, runs the risk that a copy could be in more than one collection, so you would want to put some information (and a corresponding method) on the copy as well.
Not pretty sure for the exact justification , but you can think it this way, IF multiple patients go and visit a doctor, its only the doctor who know when to call in the next patient, so the next method would be a part of Doctor's Responsibility, though its tempting to think that next should be the part of Patient's responsibility as he has to go next, someways when the library book is to be issued, it should be the responsibility of book genre rather patron as book(RESOURCE) knows when it will be free .
Is a method something that the object does, or something that’s done to it? Or is this a different concept entirely?
Let me clear something about class and objects first. Class are generally used to a denote particular category. Like
Cars not Ferrari, or Porsche
Fruits not Banana, or Apple
So, it's Ferrari that is driven, and a banana that is eaten. Not their class
Its always an object that has properties and has behavior.
Even going to your case specifically.
borrow() method is an action/behavior done by a object of a person on an object of book whose records is kept by another object of the library system itself.
A good way to represent this in OO way for me would be like
libray.borrow(new book('book title'), new person('starx'));
Just for fun, What do you think about this
person starx = new person('starx');
book title1 = new book('title1');
library libraryname = new library('libraryname');
libraryname.addBook(title1);
if(starx.request(title1, libraryname)) {
starx.take(library.lend(title1, starx));
}
I guess it can go either way. There is no hard and fast rule for it. The idea is the group functions logically that makes sense. To me, Patron#borrow(BookCopy) make same sense as BookCopy#borrow(Patron). Or you may have a class LibManager.borrow(BookCopy, Patron).
Your instructor's right. Well, actually, he's wrong. I don't know.
My point is, for questions such as this, there are often no firm general answers one way or another. It largely comes down to what works best in your particular case. Go with whatever's easiest to code - it'll be the easiest to maintain. And, by "easiest to code", I suggest also taking into account the intended users of the classes (beyond just your Library, Copy and Person classes).
I was thinking about precisely that today. I came to this conclusion:
Whichever makes more sense in the appropriate context.
We recently had a code review . One of my classes was used so that I could return/pass more than one type of data from/to methods . The only methods that the class had were getters/setters . One of the team's members ( whose opinion I respect ) said that having a class like that is bad practice ( and not very OOP ) . Why is that ?
There's an argument that classes should either be "data structures" (i.e., focus on storing data with no functionality) or "functionality oriented" (i.e., focus on performing certain actions while storing minimal state). If you follow that argument (which makes sense but isn't always easy to do) then there is nothing necessarily wrong with that.
In fact, one would argue that beans and entity beans are essentially that - data containers with getters and setters.
I have seen certain sources (e.g., the book "clean code") arguing that one should avoid methods with multiple parameters and instead pass them as a single object with getters and setters. This is also closer to the "smalltalk model" of named parameters where order does not matter.
So I think that when used appropriately, your design makes sense.
Note that there are two separate issues here.
Is a "struct-like" class sensible?
Is creating a class to return multiple values from a method sensible?
Struct-like classes
An object class should -- for the most part -- represent a class of real-world objects. A passive, struct-like java bean (all getters and setters) may represent a real-world thing.
However, most real-world things have rules, constraints, behaviors, and basic verbs in which they engage. A struct-like class is rarely a good match for a real-world thing, it's usually some technical thing. That makes it less than ideal OO design.
Multiple returns from a method
While Python has this, Java doesn't. Multiple return values isn't an OO question, per se. It's a question of working through the language limitations.
Multiple return values may mean that an object has changed state. Perhaps one method changes the state and some group of getters return the values stemming from this state change.
To be honest, it sounds fine to me. What alternative did the reviewer suggest?
Following OOP "best practices" and all is fine, but you've got to be pragmatic and actually get the job done.
Using Value Objects like this (OO speak for 'struct') is a perfectly legitimate approach in some cases.
In general, you'll want to isolate the knowledge needed to operate upon a class into the class itself. If you have a class like this, either it is used in multiple places, and thus can take on some of the functionality in both of those places, or it is in a single place, and should be an inner class. If it is used in multiple ways, but in completely different ways, such that there is no shared functionality, having it be a single class is misleading, indicating a shared functionality where there is none.
However, there are often specific reasons for where these general rules may or may not apply, so it depends on what your class was supposed to represent.
I think he might be confusing "not very OOP" for bad practice. I think he expected you to provide several methods that would each return 1 value that was needed (as you will have to use them in your new class anyway that isn't too bad).
Note that in this case you probably shouldn't use getters/setters, just make the data public. No this is "not very OOP" but is the right way to do it.
Maybe Josh Bloch offers some insight into this here.