So in my assignment (UB) I have to use a String array for passing data to my database. I have decided to write my dao using the String array for all required actions and then have a POJO at the high levels for transferring over the network etc. I have a utility class for converting from the String array to POJO (it will do it back too). The POJO verifies the arguments are correct in all setters. These are hard coded (lengths, formats etc) according to the assignment instructions.
I am trying to keep the dao layer completely separate to the other layers. It uses the data structure it learns dynamically from the database file. This way I can put the case that if the underlying storage changes the rest of the application needs no significant changes. I therefore need further checks to verify the String array is valid for the database used. This requires another set of checks and mostly duplicated code but will keep the data layer separated. Do you think this is an acceptable (and good) strategy?
My Data class verifies if the String is a valid one according to the database schema (which is dynamically read). If it's not a valid String an IllegalArgumentException. This exception is never caught in the program because you as a developer should provide correct String when you invoke any method from the Data class.
In my business service implementations I provide business validations, like making sure the entered customer id has 8 digits. The pojo I use for transferring data from server to client (and vice versa) has no validations at all, it even has no getters/setters, just public data members, because it's only purpose is transferring data.
Your data class sounds similar to what I am implementing. My concern was how far do you go to protect your database from invalid data passed from a higher layer. I fully intend to verify all data before it gets there but if this application was at a later date extended by the 'Junior Programmer' (that's my role now for now ) and he/she tried to pass a valid String but with for example a different date format. Using the dynamically learnt database schema on allows so much to be validated and this would ultimately be written to the database. Is it a case that at some point the usage contract (javadoc) takes over from the coded checks?
I am considering having a check in the utility class to check for a valid structure but this would also suggest that the database structure is validated to otherwise the utility class is pointless if the database format changes. This does remove the separation between the layers though.
Thanks for your input Roel. I've read a great many interesting posts by yourself and other ranchers here. They are much appreciated.
I don't consider the date format as one of the checks you should do in the Data class, because everything in there is a String. I check the length of each String, the number of elements in the String and if a String doesn't contain illegal characters (= chars which couldn't be converted with the charset I use).
Is it a case that at some point the usage contract (javadoc) takes over from the coded checks?
If your code does not follow the contract, you have a problem in my opinion. If your contract says A and your code does B, you are violating the contract. And if I have to develop a part of the application which is dependent on that method, I will hunt you down and do with your head
I used the strategy pattern in the DB implementation by passing a set of FieldConstraints to the constructor:
(The PersistenceProvider is an own class and not the interface javax.persistence.spi.PersistenceProvider)
The configuration of these constraints can be either by a config file or a hardcoded schema factory. My implementation chose the latter:
The validation is done before the update and create is executed.
Any other layer can use the same DBFieldConstraint derivations for validating the field e.g. in the business layer. -> No code duplicating.
The Data.java implementation stays completely free from all assumptions beside the real binary DB format.
Of course the number of field constraints (and the position in the array -> therefore a formal ArrayList and not just a List) must match the schema of the underlying data file.
BTW: as the constructor shows: the Data implementation does neither know about the storage. It is supplied with a InputStream to load the first time, and with a PersistenceProvider where it ask for a output stream when it needs to write back to persistence.
Heri Bender wrote:Any other layer can use the same DBFieldConstraint derivations for validating the field e.g. in the business layer. -> No code duplicating.
In my opinion in the business layer other validations will occur and inherently there will be no code duplication. For example the business layer will validate if the customer id is a 8 digit number. This is a business rule, not a database constraint. In your Data class you will only check for database related validation rules (like length of a field, null values,...). And of course the business layer (and its developer) is (are) responsible for passing a valid String to the Data class.
Furthermore I don't know if you want other layers than your database layer to be capable of validating fields.