Programmer, solution architect, user group and conference organizer, conference speaker and traveling fun code evangelist. Johannes tries to apply Agile principles to large software projects, but what he's really passionate about is sharing the experience of more fun programming with other coders around the world. Johannes is a DZone MVB and is not an employee of DZone and has posted 35 posts at DZone. You can read more from them at their website. View Full User Profile

How Changing Java Package Names Transformed my System Architecture

07.19.2012
| 6989 views |
  • submit to reddit

Changing your perspective even a small amount can have profound effects on how you approach your system.

Let’s say you’re writing a web application in Java. In the system you deal with orders, customers and products. As a web application, your classes include staples like PersonController, PersonRepository, CustomerController and OrderService. How do you organize your classes into packages?

There are two fundamental ways to structure your packages. Either you can focus on the logical tiers, like com.brodwall.myapp.controllers, com.brodwall.myapp.domain or perhaps com.brodwall.myapp.services.customer. Or you can focus on the domain contexts, like com.brodwall.myapp.customer, com.brodwall.myapp.orders and com.brodwall.myapp.products. The first approach is by far the most prevalent. In my view, it’s also the least helpful.

Here are some ways your thinking changes if you structure your packages around domain concepts, rather than technological tiers:

First, and most fundamentally, your mental model will now be aligned with that of the users of your system. If you’re asked to implement a typical feature, it is now more likely to be focused around a strict subset of the packages of your system. For example, adding a new field to a form will at least affect the presentation logic, entity and persistence layer for the corresponding domain concept. If your packages are organized around tiers, this change will hit all over your system. In a word: A system organized around features, rather than technologies, have higher coherence. This technical term means that a large percentage of a the dependencies of a class are located close to that class.

Secondly, organizing around domain concepts will give you more options when your software grows. When a package contains tens of classes, you may want to split it up in several packages. The discussion can itself be enlightening. “Maybe we should separate out the customer address classes into a com.brodwall.myapp.customer.address package. It seems to have a bit of a life on its own.” “Yeah, and maybe we can use the same classes for other places we need addresses, such as suppliers?” “Cool, so com.brodwall.myapp.address, then?” Or maybe you decide that order status codes and payment status codes deserve to be in the “com.brodwall.myapp.order.codes” package.

On the other hand, what options do you have for splitting up com.brodwall.myapp.controllers? You could create subpackages for customer, orders and products, but these subpackages may only have one or possibly two classes each.

Finally, and perhaps most intriguingly, using domain concepts for packages allows you to vary the design according on a case by case basis. Maybe you really need a OrderService which coordinates the payment and shipping of an order, while ProductController only needs basic create-retrieve-update-delete functionality with a repository. A ProductService would just get in the way. If ProductService is missing from the com.brodwall.myapp.services package, this may be confusing or at the very least give you a nagging feeling that something is wrong. On the other hand, if there’s no Controller in the com.brodwall.myapp.product package, it doesn’t matter much.

Also, most systems have some good parts and some not-so-good parts. If your Services package is not working for you, there’s not much you can do. But if the Products package is rotten, you can throw it out and reimplement it without the whole system being thrown into a state of chaos.

By putting the classes needed to implement a feature together with each other and apart from the classes needed to implement other features, developers can be pragmatic and innovative when developing one feature without negatively affecting other features.

The flip side of this is that most developers are more comfortable with some technologies in the application and less comfortable with other technologies. Organizing around features instead of technologies force each developer to consider a larger set of technological challenges. Some programmers take this as a motivating challenge to learn, while others, it seems, would rather not have to learn something new.

If it were my money being spend to create features, I know what kind of developer I would want.

Trivial changes can have large effects. By organizing your software around features, you get a more coherent system that allows for growth. It may challenge your developers, but it drives down the number of hand-offs needed to implement a feature and it challenges the developers to improve the parts of the application they are working on.

See also my blog post on Architecture as tidying up.

Published at DZone with permission of Johannes Brodwall, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Sivaprasadreddy... replied on Fri, 2012/07/20 - 4:10am

Hi  Johannes Brodwall,

I like the idea of package by feature which greately reduces the time for moving across the packages while coding and all the related stuff will be at one place(package). But what about interactions between the services in different packages?

Suppose we are building a blog app and we are putting all user related operations(controllers/services/repositories) in com.mycompany.myblog.users package. And all blog post  related operations(controllers/services/repositories) in com.mycompany.myblog.posts package.

Now I want to show User Profile along with all the posts that he posted. Should I call myblog.posts.PostsService.getPostsByUser(userId) from myblog.users.UserController.showUserProfile()?

What about coupling between packages?

 Also wherever I read about package by feature, everyone says its a good practice. Then why many book authors and even frameworks encourage to group by layers? Just curious to know :-)

 Thanks,

-Siva 

Balint Persics replied on Fri, 2012/07/20 - 10:09am in response to: Sivaprasadreddy Katamreddy

"Also wherever I read about package by feature, everyone says its a good practice. Then why many book authors and even frameworks encourage to group by layers? Just curious to know :-)" 

Frameworks group services by layers because what they really provide is infrastructure to build applications. The framework will not know which part of it is used by your application: persistence, task parallelism, security etc. That's why infrastructure code is organized by layers. Because the features of framework code is layers of infrastructure provided to applications. So frameworks organized by layers are really frameworks organized by features. 

 

"Suppose we are building a blog app and we are putting all user related operations(controllers/services/repositories) in com.mycompany.myblog.users package. And all blog post  related operations(controllers/services/repositories) in com.mycompany.myblog.posts package. Now I want to show User Profile along with all the posts that he posted. Should I call myblog.posts.PostsService.getPostsByUser(userId) from myblog.users.UserController.showUserProfile()" 

You should stick to the single responsibility principle. Showing posts AND user profile is a separate responsibility from showing user profiles OR showing posts.

If you want to show data from different sources, it should be a separate responsibility (creating a mashup is different from anything else), let's say UserPage. And the UserPage entity is collaborating with the PostService and the UserService to achieve it's goal: generate a page composited from separate data. It's neither the PostService's nor the UserService's responsibility to create this composite page.

 "What about coupling between packages?"

Coupling should exist between business objects (dependent entities) and not just packages. OO code should reflect the problem domain, and depdendencies and coupling between packages and classes should reflect real depdendencies between problem domain objects. Tighlty coupled code without coupling existing in the problem domain is bad code. Very bad code.

Jose Fernandez replied on Sun, 2012/07/22 - 2:09am

I group my code by feature as well and I find it works wonders for separation of concerns. It is all but required if you write modular software, say for OSGi.

Maatari Okouya replied on Sun, 2014/08/03 - 11:06am

I'm trying to get into understanding properly the package by feature approach.

1 - Let say I have 2 features that tap on the same data. For instance, one feature could be visualizing bank account information with different sophisticate possibilities. The other feature is about making transaction from the bank account (We could well imagine that this feature does not involve visualization, it could be simply provided as a rest service).

.

1.a - The data model is shared across two features here. How does that impact the package by features. Shall we create redundant data models class in the 2 package ? Shall we create a specific package for the data model instead?

which leads me to the second question?

2- In general how are cross-cutting concern dealt with ?

.

2.a - For instance the case above when it comes to the data model?

.

2.b - Or, when it comes to the database access or some common access to an external service (shared by different feature but doing something different with it)?

.

2.c - Else, the front-end or the overall bundling of the application in general.

What i mean here, is the following case: Currently i have an application which has

(i) a message transfer capability (between participant of the system)

(ii) It also has the messaging monitoring capability whereby it automatically detect rules violation and give penalties.

(iii) A visualization capability dedicated to the administrator of the system. (iv) A notification capability provided to the administrator of the system to send message to participants.

(V) A violation cancellation capability for the admin as well. And so on.

The point is all of it has to be packaged in one application that i call marketplace infrastructure. Should the marketplace infrastructure that wires everything together have his own package ? Even if it is not a feature.

I think the same could be applied some how in a Web-application as well. There has to be one central point that bundles all the feature modules / packages altogether. If each module define routes, controllers etc... There should be a central routes that import all routes for instance.

If the application has a database behind, this database is used by different feature, well who is going to start the database and wire every modules.

So bottom line is: what about the cross functional stuff (data models, service access and etc..) and the bundling (wiring everything together).

PS: By wiring i think about dependency injection, still the graph of object has to be defined somewhere.

Many thanks for any help.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.