0

With object-oriented programming in mind, how does the database come into play with objects? Like for example, let's say there is a Student class, with attributes like name, number, courses, etc

The Student class also has behaviour (methods). Some that I think will be appropriate are enrollForACourse(), dropACourse(), getStudentGPA(), getAllStudentCourses() etc, or something like that. I'm not sure if those example methods are good in terms of cohesion, but I would say yes or maybe.

What I kind of want help with is the database part. So if another different object, or a user or something wants to know the courses the student has, then the getAllStudentCourses method on the Student class will be used. But inevitably, that information is stored in a database.

So would the getAllStudentCourses() method on the student class make a query to the database for this info? Is this good practice? and would this follow object-oriented design? Etc Same for enrollForACourse().

What if the Student class needs to query an outside 3rd party service in a method?

1 Answer 1

1

I point out some notes to help you. There are many factors to model communication with a database.

  • ORMs: Object Relation Mapping is a technique for converting data between a relational database and objects in your program. ORMs are different in details but they do the same thing: Fetching an entity and converting it into a specified object. And doing CRUD operations on the entities. For example, Django ORM (in Python) uses the active record pattern. The entities are responsible for committing their changes. But in Entity framework (.NET c#) the entities don't know about database connections and how to commit their changes. The wrapping container (DbContext) does the work. In this way, you can apply the unit of work pattern.
  • Application architecture: There are many architectures you can use for your application that affect your way of retrieving and modifying data. For example, CQRS architectural pattern, makes you use separate models for reading and writing data.
  • Design Patterns: Some design patterns illustrate how to work with data. Repository and Unit of work patterns are the most important ones. The repository pattern states that you should define an interface that works like an in-memory collection. If you have a User table, you should have an interface IUserRepository that represents the table. It includes all required methods such as CRUDs that your client needs. The unit of work helps you to commit all your changes in one transaction or roll back all of them if anything goes wrong.

About your examples, some of them modify the state of your data we call them commands. Commands can have correspondent behavior (methods actually) in your entity object. enrollForACourse and dropACourse() are examples of commands. But for getStudentGPA() and getAllStudentCourses(), they are queries that other objects like repositories or (query handlers in CQRS) are responsible for. Don't put your queries in the entity itself. Queries are complex and your entity should not be polluted by these complexities.

GRASP principles are trying to assign responsibilities to classes. All these techniques, patterns, and practices came in to comply with GRASP. So from the object-oriented POV, you should not put extra responsibilities in the entity.

I'm not sure if those example methods are good in terms of cohesion, but I would say yes or maybe.

I say it depends. Some of these are simple and can be handled by Navigation properties (properties that reflect the relation between two tables) like all four of your examples and some of them are complex queries or commands that involve multiple entities to handle (like CanStudentEnrollInACourse()). In these cases, you should use repositories or query handlers. Because the responsibility doesn't fall in the entity's territory.

So would the getAllStudentCourses() method on the student class make a query to the database for this info? Is this good practice? and would this follow object-oriented design? Etc Same for enrollForACourse().

Yes, it's acceptable as long as the implementation doesn't include any data access logic, like navigation properties (ORM must support this feature).

What if the Student class needs to query an outside 3rd party service in a method?

Why would it need to query over another service? Is it possible to pass the result to the entity? If not, you can pass the 3rd party service interface to your entity. Your entity won't be pure but the responsibilities are more clear this way.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.