Bill K
Bill K

Reputation: 62789

Looking for the best way to make a web framework more OO on the server side

Web frameworks seem to always wander away from good OO code (Where you group code and data together in an object, think in terms of sending messages to that object, etc)

The main problem seems to be the existence of the bean pattern. You use a bean pattern (often called POJOs these days because people don't seem to understand the difference) to interact with the database, web services and most other things.

So no you are stuck with this ball of setters and getters with no code--so you tend to add a bunch of--well essentially static functions to manipulate these things. Nearly all the advantages of OO code are gone.

I see three solutions I'm considering, but wanted to hear if there were any serious disadvantages to any of them.

1) use a POJO pattern instead of a bean pattern. This would mean eliminating setters and getters from your POJOs (so you can have encapsulation/data safety) and instead adding business logic methods. This seems to make the most sense--in fact I think it's why libraries like hibernate switched away from requiring Beans to allowing POJOs, yet everyone still seems to use a bean pattern instead.

2) extend your Bean with a business logic class that uses the bean's fields as storage. This seems flakey and problematic, but would be very easy to drop into an existing codebase as a way to migrate...

3) Wrap a Bean pattern object with a business-logic object. Mostly I think this might be necessary if #1 is really problematic.

What I'm mostly wondering is why I've never seen #1 used. I'd really love to hear from anyone who used the Pojo pattern (With business logic and without setters and getters) for hibernate objects and had problems with it (or had it work really well)...

Upvotes: 2

Views: 180

Answers (6)

hvgotcodes
hvgotcodes

Reputation: 120268

I'll change my comment into an answer. I basically disagree with your opening premise

Web frameworks seem to always wander away from good OO code.

Nothing in Java EE or a Spring/JPA model "wander[s] away from good OO code". That fact that a JPA provider like hibernate allows POJOs doesn't mean that you can't use a rich domain model, that defines the business logic in the beans. For Java web apps, I have seen it done both ways -- rich domain model, or an anemic domain model with the business logic in the service layer, which isn't necessary non-OO or a bad design.

I think maybe what you meant to say is a lot of apps are not written with proper design and/or proper OO. That I will agree with. But that has nothing to do with the frameworks....

So your proposed solutions all basically say "properly design your application with good OO principles". Option 1 is the simplest.

Upvotes: 3

Marko Topolnik
Marko Topolnik

Reputation: 200226

There are good reasons to keep (most of) business logic outside the data objects, but optimal design will include certain parts of it there. This is not exactly easy to get right, especially in a blue-collar team setting, which is I guess 95% of all Java dev teams out there.

I like to put some simple, self-contained, widely reusable pieces of logic into my data objects; code that is inherently coupled to that data without regard to any specific business request. Examples would be some conversions, validations, etc.

As far as getters and setters, I avoid them at all costs. You could use public final fields, or just plain public fields. The getter+setter combo gives you exactly as much encapsulation as a public field: zero.

As far as ORM solutions, I use Hibernate strictly as a convenience over SQL, and never as a persistent state manager. The mapped classes are there only as a replacement for XML mapping; they are never even instantiated in read operations. For inserts I save each object individually, which maps one-to-one with a single database row, without transitive persistence. This basically means that my Hibernate model objects are just a Java way of looking at database rows (plus the convenient join column specifications—HQL looks much nicer without those redundant join criteria).

Upvotes: 1

millimoose
millimoose

Reputation: 39980

"What I'm mostly wondering is why I've never seen #1 used." Separation of concerns, the single responsibility principle (probably most of all), testability, etc. The model of "everything is coupled to everything" is convenient, but objectively terrible. (This is not saying that convenient API surfaces are bad, but they should be built OVER well-factored, testable code, not instead of it.)

For instance, when you add a "dumb" DTO layer over your business logic layer, where every view is mapped to a bean that contains everything needed to create the view, you get rid of problems like having to keep a session open to fetch associated properties, or wrangling the ORM into fetching them eagerly. (The former also implies having the N+1 selects problem which increases database roundtrips.)

It also makes keeping track of transaction scope easier if every request is served by a single method call on a dedicated service layer. This call is then a single logical operation over the data, which makes setting up transaction handling trivial.

Last but not least this approach leads to small classes that are easier to understand and change on their own. E.g. if you need to change the algorithm for calculating grade point averages you start in GradePointAverageCalculator and navigating from there, instead of the scope of code you need to look at being "Student.java, lines 1340 through 1486, then 1502 through 1689, …"

Upvotes: 0

Tobb
Tobb

Reputation: 12215

Perhaps you could look into the Model-View-View Model design pattern used by amongst other Knockout (a javascript framework). Here the View Model is introduced as a layer between the Model and View, giving the posibility of separating the view from the model.

Read more about it here: http://knockoutjs.com/documentation/observables.html ..and here http://en.wikipedia.org/wiki/Model_View_ViewModel

Upvotes: 0

matt b
matt b

Reputation: 140011

I'm confused on what exactly you are arguing here, as you say both that people tend to call beans "POJOs" then you suggest that instead of using beans you use "POJO". But to respond to this point:

So no you are stuck with this ball of setters and getters with no code--so you tend to add a bunch of--well essentially static functions to manipulate these things. Nearly all the advantages of OO code are gone.

I disagree with this - if you are writing static functions to manipulate your objects, something with your design is wrong.

Typically the common/"best" practice is that you wrap your business logic in a "service layer" of classes that knows how to manipulate the data (represented in your beans, POJOs, domain objects, whatever you want to call them) in response to the rules of the application.

No one is stopping you from having your "service layer" be OO-designed, with subclasses and inheritance and all that.

Typically, you won't see someone build an application where the Employee class that holds the data also contains methods and logic that perform operations on the Employee, as people tend to want to separate the data (represented by the Employee class) from the logic. And also practically speaking, once you start having methods that operate on the employee instances in the Employee class, then you need to have the Employee class be capable of calling into the storage layer itself, and now the class that you use Hibernate to represent the results of queries (the Employee class) also has references to Hibernate code to load itself, and it becomes a giant mess.

I think that the "problems" you see are just disagreements you have with the design ideas that are common with these types of applications. Most people want to separate how the data is represented from the code encapsulating the logic of the application.

Upvotes: 1

Yogendra Singh
Yogendra Singh

Reputation: 34387

Per best practice, the business logic should be separate from presentation logic. Most of the web frameworks provide nice features around presentation of the data. Any business logic involved in data retrieval/manipulation should be written in Business Layer, which is an additional layer between the presentation layer and data layer. POJO object behave as data carrier between Business Layer and Presentation Layer. POJO are really good candidate for this because they are very light object having attributes as accessor methods.

Rest is up to you. If you want to use complex bean objects with business logic in them, I don't think that any web frameworks stops you from doing that.

Hope this helps.

Upvotes: 0

Related Questions