6

Where in the code do I best put object creation (stateful objects) and where not? In what layers?

For example, I once put an object reference inside a Hibernate DAO class and I was told that this was incorrect because DAO classes are not supposed to have state. State should be inside the 'service layer'.

I have been told that I should not create new objects on recurring method calls such as UpdateCart(). Creation of objects is costly and should not be sitting in your code everywhere. It should be sitting in initialization type methods only. For example, if an e-commerce application needs a cart, put it in the session. If it needs some general main object, put it in the initialization code. Create it once there and let the rest of the application access its instance later. Do not create this instance upon every call.

I'm confused about this whole design principle. The strangest thing I heard is 'an app is not supposed to have state. State should be kept in the data layer where the database is'. Really? I'm quite new to these design concepts and I don't know where to look in order to get more educated on it. GoF? Design Patterns books? The goal is to create qualitative code (i.e. to be used in the business).

Thanks

MrStack
  • 455
  • 1
  • 7
  • 21

2 Answers2

2

What is good practice can vary base don the type of project it is.

For most projects, creating objects is not that expensive for the CPU. A cost which is not always articulated well is the cost to the design. It appears your application has a design methodology where all the state and objects need to be managed in a controlled and centralised way. This is often done to improve maintainability and simplify the design. I wouldn't assume you should just know what the design is unless it has been very clearly spelt out to you.

I suspect they rest of the team are used to working a particular way and don't think they should have to document or teach you this methodology, just tell you when you got it "wrong". This is not productive IMHO, but you have to deal with the situation you have and ask them questions when it comes to the placement of state or data structures.

Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • Well, the person reviewing my code said that object creation is costly in the web layer. Regardless of CPU cost, we keep it very conceptual. While the aforementioned approach may be used to simplify the design - I don't think that that's what was actually meant. The person told me "every time the user visits the webpage, you are newing up the person's profile manager and getting the profile data from there. This is too costly. The manager should be instantiated once only and the rest of the web app components can later access it by getting it from an application attribute." app.setAttribute(m) – MrStack Sep 23 '12 at 10:22
  • Is "profile manager" some kind of DAO or Service? In general, creating a small fixed number of objects per request is rarely if ever "too costly". Allocating objects is incredibly fast on a modern JVM. Of course if it's totally not needed, since this manager is effectively a singleton anyway, then don't create one (but in that case I wonder, could you guys not just as well use static methods, why have even 1 instance if you can seemingly do with 0 instances as well?) – Arjan Tijms Sep 23 '12 at 11:25
  • The act of creating a simple object could cost about 10 ns. Creating large numbers of them can add up but even a million might be acceptable. Where the cost can be much higher is when you have to build the information based on an external source. A single database query can cost/take 10 ms, and if you have to do many of them for a single profile, this can quickly become around one second which is unlikely to be a good idea to do each time. – Peter Lawrey Sep 23 '12 at 14:13
  • Arjan, the context was a J2EE6 web application with Servlets. These Servlets are singletons. Each request is a Thread object. Each time a Servlet is visited (e.g. webpage form button is clicked), a new thread is created. Creating a new object per request can be costly (theoretically). – MrStack Sep 25 '12 at 10:58
  • Can you not avoid creating a new thread per request as this is expensive in itself? Can you use a fixed size thread pool as this would solve your problem as well? – Peter Lawrey Sep 25 '12 at 11:04
  • A Thread pool is one of the standard implementations of request handling - yes. The problem is putting heavy objects in each Thread - something to be avoided. – MrStack Sep 25 '12 at 12:44
  • A thread pool doesn't create a new thread for each request and if you create a thread local object you will never have more objects than the size of the pool. – Peter Lawrey Sep 25 '12 at 12:46
  • In that case, what is the problem with using thread local objects? – Peter Lawrey Sep 25 '12 at 13:51
  • The problem is putting newing up thing inside the Singletons (the Servlets). Newing up should be done once in some other backup class. – MrStack Sep 25 '12 at 15:03
  • It can be done in advance, using an object pool. You could just the use object pool, recycling object when you are finished with them, or select from the pool with each thread local once. – Peter Lawrey Sep 25 '12 at 15:05
1

'an app is not supposed to have state. State should be kept in the data layer where the database is'

There are designs where this is the norm, aptly called 'stateless architectures'. Whether every architecture should be stateless is of course doubtful and the very term is perhaps opens to debate as well.

Most "stateless" applications in fact do have state, but as the rule above states (no pun) this state is kept in one global place; the database. As Peter mentions, the reasons for this might be maintainability and simplification, but it's also often heard that this is for scalability. Without state appearing anywhere but in the database, it's thought to be easy to add additional front-end servers, processing servers, and what have you.

While this has some merit indeed, I think we do have to make a distinction between temporary state and authoritative state.

Temporary state can be something like the place you are in an ordering process and the details you have already entered. In Java EE, you could keep this around in e.g. @ConversationScoped beans, or @Stateful beans. This is thus state that you keep inside the web layer resp. business layer.

The advantages of this are ease of use, performance and unloading your single central database. Sure, you can store temporary state in your central database as well, but you probably want to keep this away from the regular, non-temporary data, which means some additional programming complexity is needed. It's also typically much faster to retrieve data from the web layer, and it removes some load from the database.

In many systems there's only a single master database (a database accepting writes), so this single database might become a huge bottleneck in that setup.

Depending on your actual architecture and setup, not keeping temporary state in the database -may- actually improve your ability to scale.

The disadvantages are that you do need your client to stick to the single server on which the temporary state is currently kept. This is typical called 'sticky sessions'. If the one server where this client is interacting with fails or needs to be restarted or whatever, the client will loose this temporary data. There are some schemes like replicating state to all nodes in a cluster or to nearby nodes (buddy replication), but this is making things complicated again and may overload the network (if all nodes are constantly replicating to each other).

Authoritative state means it represents shared data that is the sole source of information. This kind of state is something we almost always like to have at a central location, but sometimes you'd see it being stored in e.g. a web node.

For example, suppose we have a list of recent prices, and instead of persisting this to a central location we keep it on the web node where it was entered. Now there's a concept of the "one and only" web node that has this information and other servers may start assuming there's only this "one and only" web node. Adding additional nodes is now impossible, since it breaks this assumption.

Arjan Tijms
  • 36,666
  • 12
  • 105
  • 134