Page History
...
- CRUD methods (Create & Retrieve methods are static)
- All business logic methods
- Database logic (queries, updating, …)
- All getters & setters of the object
- ….
Working with these types of GOD classes, we get the following disadvantages:
- By grouping all of these different functionality's into a single class it is sometimes hard (impossible ?) to see which methods are setters/getters/business logic since everything is thrown onto a big pile.
- Makes it very hard to make/track local changes since you need to overwrite the entire class to make a small change.
- Refactoring/altering GOD classes becomes hard since it is unclear where the database logic begins & where the business logic is located.
Database layer access
All database access is made through a DatabaseManager, this object can be accessed from any object (even the user interface can make database calls).
Any object can query any table, some examples:
- EPerson table is queried from the Groomer and EPerson class.
- Item is queried from the LogAnalyser, Item, EPerson classes
This makes it hard to make changes to a database table since it is unclear from which classes the queries are coming from. Below is a schematic overview of the usage of the item class:
Postgres/oracle support
Since DSpace supports both postgres AND oracle this classes contains a lot of “if postgres do X or else if oracle do Y”. This tends to lead to bugs & makes support for 2 database system hard to maintain.
Since every query needs to be run again oracle and postgres, developers need to write 2 queries or use query concatenation which can lead to very hard to read queries, below is an example of such a query:
Code Block | ||||
---|---|---|---|---|
| ||||
String params = "%"+query.toLowerCase()+"%"; StringBuffer queryBuf = new StringBuffer(); queryBuf.append("select e.* from eperson e " + " LEFT JOIN metadatavalue fn on (resource_id=e.eperson_id AND fn.resource_type_id=? and fn.metadata_field_id=?) " + " LEFT JOIN metadatavalue ln on (ln.resource_id=e.eperson_id AND ln.resource_type_id=? and ln.metadata_field_id=?) " + " WHERE e.eperson_id = ? OR " + "LOWER(fn.text_value) LIKE LOWER(?) OR LOWER(ln.text_value) LIKE LOWER(?) OR LOWER(email) LIKE LOWER(?) ORDER BY "); if(DatabaseManager.isOracle()) { queryBuf.append(" dbms_lob.substr(ln.text_value), dbms_lob.substr(fn.text_value) ASC"); }else{ queryBuf.append(" ln.text_value, fn.text_value ASC"); } // Add offset and limit restrictions - Oracle requires special code if (DatabaseManager.isOracle()) { // First prepare the query to generate row numbers if (limit > 0 || offset > 0) { queryBuf.insert(0, "SELECT /*+ FIRST_ROWS(n) */ rec.*, ROWNUM rnum FROM ("); queryBuf.append(") "); } // Restrict the number of rows returned based on the limit if (limit > 0) { queryBuf.append("rec WHERE rownum<=? "); // If we also have an offset, then convert the limit into the maximum row number if (offset > 0) { limit += offset; } } // Return only the records after the specified offset (row number) if (offset > 0) { queryBuf.insert(0, "SELECT * FROM ("); queryBuf.append(") WHERE rnum>?"); } } else { if (limit > 0) { queryBuf.append(" LIMIT ? "); } if (offset > 0) { queryBuf.append(" OFFSET ? "); } } |
Overview
Content Tools