Interfaces in an N-Tier application



  • Say you are building an application using a layered architecture. Thus you have an UI layer, a business logic layer and a data layer. You have implemented the bussiness classes in your business layer.

    You have written the public interfaces of the business classes in such a way that they guarantee safe usage. Thus, the higher level UI layer can use the business classes without any problems.

    Now you want to write the data layer. Now you are presented with a problem, in order to load business objects with data from a database, you have to define properties or getters and setters in your business classes. These properties have to be public. Now the interface does not guarantee safe usage anymore, since someone that is developing the UI layer could use these properties to set invalid data. The getters and setters could check for the validity of the data, but the truth is, the UI layer has no business in using these getters and setters.

    The thing is, the interface of the business classes for the UI layer should be different from the data layer. The UI layer should not be able to do the same thing to the business objects that the data layer does.

    How do you solve a problem like this? Are there an patterns that take care of this?

     



  • You could solve that by using a factory pattern: The business layer creates a factory that produces business objects and passes the factory to the database layer. The business classes have no public constructor, so only those factories created in the business layer (e.g. anonymous classes in Java) can create instances of business classes.

    // SampleFactory.java
    public interface SampleFactory {
        public Sample createSample(String id, String payload);
    }

    // Sample.java  => Business layer
    public class Sample {
        private String id;
        private String payload;
        private Sample() {}
        private Sample(String id, String payload) {
           this.id = id;
           this.payload = payload;
        }
        public static Sample getInstance(String id) {
            return SampleData.load(id, new SampleFactory() { public Sample createSample(String id, String payload) { return new Sample(id, payload); } } );
        }
    }

    // SampleData.java => Database layer
    public class SampleData {
        public static Sample load(String id, SampleFactory f) {
           // database access goes here
           String payload="42";

           return f.createSample(id, payload);
        }
    }




  •  Why not just let the business objects implement different interfaces, and then pass them to the ui layer as a different interface type? I mean, you can't prevent people from casting you objects then, but at least its clear what you do. For validation, you can use something like hibernate validator, or write proxy classes implementing the UI data interfaces. You could also define extra aop rules, issuing javac warnings or compile errors if you want to enforce people not to cast your objects and you find it impractical to prevent it otherwise (like throught the usage of proxy classes). Does that make sense? :)



  • I get what you are both are saying, after reading AmmoQ's code a few times. It is pureley theorethical, but I ran into it when doing a project at school.

    However, i think it is practical in a real life job to try to design your program so that people developing other layers can't molest your business objects.



  • What do you want to acheive? Complete separation? Then you can use the DTO pattern, but personally I think it is way too cumbersome. I usually send all entities to the frontend for modification, and then I let the controllers pass the entity to DAO:s to handle validation and save. I don't really see what you are trying to protect, maybe we have different structures in our apps? Could you elaborate?



  • @Ice^^Heat said:

    However, i think it is practical in a real life job to try to design your program so that people developing other layers can't molest your business objects.

    It's impossible to "protect" data from code that's handling it, except perhaps through encryption - and then only if the suspect code is merely transporting the data to a third party and not doing anything with it.

    You have to realize that encapsulation (making stuff private) is NOT a security feature in any way. It's merely an organization feature, a way to tell other developers "hands off, there are no guarantees if you mess with this".

    Are you aware that it is quite possible to access private methods and variables from other classes? In C++, you can do anything with a pointer anyway, in Java there's java.lang.reflect.AccessibleObject, and .NET most likely has a similar feature.


Log in to reply