4

I have a hierarchical data model and am trying to implement their CRUD operations in my Web Application.

Currently I have code inheritance for CRUD operations of my entities (resources) as follows:

ResourceCommonProcedures as a base class and each Resource procedure inheriting the base class.

public class ResourceCommonProcedures { 

    public Response create(Request request){
        Response response = new Response();
        int resType = this.getResourceType(request);

        ResourceCommonProcedures rp = getResourceController(resType);
        response = rp.create(request);

        return response;
    }

private ResourceCommonProcedures getResourceController(int resourceType){
            //..

            switch(resourceTypeName){


            case Resource1:
                return new R1Procedures();

            case Resource2:
                return new R2Procedures();

            case Resource3:
                return new R3Procedures();
            ............... 

}
}

Class R1Procedures extends ResourceCommonProcedures{


public Response create(Request request) {

        Response response = new Response();
            Resource1 resource = (Resource1) request.getContent();

            ...........
            // Converts DB structure to JPA 
            R1Converter r1Converter = new R1Converter();
            Resource1JPA resourceJpa = r1Converter.toJPA(resource);
            dao.persist();

            return response;

}
}

Class R2Procedures extends ResourceCommonProcedures{


public Response create(Request request) {

        Response response = new Response();
            Resource1 resource = (Resource2) request.getContent();

            // SOME RESOURCE 2 SPECIFIC CODE
            ...........
            // Converts DB structure to JPA 
            R2Converter r2Converter = new R2Converter();
            Resource2JPA resourceJpa = r2Converter.toJPA(resource);
            dao.persist();

            return response;


}

So currently the base has the controller code which decides which sub class method needs to be called.

So the client will call the base class create method, which will internally get the implementation class and call the specific create method.

Is this design good enough ??

Or should the getResourceController() must be taken out of base class and put in a separate class ??

Is there a design pattern specific to the case ??

  • By the way: Does your programming language support enumerations? – Philipp Mar 7 '17 at 9:53
  • @Philipp: Yes it supoorts enums – Siddharth Trikha Mar 7 '17 at 10:24
  • 2
    Then I would recommend to use an enum for resourceType. That way you can't pass an invalid value to getResourceController. You will also likely get a warning if there is an enum value not handled by your switch (unless you have a default). – Philipp Mar 7 '17 at 10:34
  • Yes. You are right. – Siddharth Trikha Mar 7 '17 at 10:36
  • 2
    @Philipp ... I'd go further. The language looks like Java, in which case you can define an abstract method in the enumeration that is implemented by the cases, so getResourceControllet can be a method of the enumeration, entirely eliminating the switch. – Jules Mar 7 '17 at 10:41
2

I would go for an abstract generic class :

public class AbstractProcedure<T extends BusinessObject, TJPA extends JPAObject, TConverter extends Converter<T, TJPA >>{

public abstract TConverter<T, TJPA> getConverter();

public Response create(Request request) {
    Response response = new Response();
        T resource = (T) request.getContent();

        ...........
        // Converts DB structure to JPA 
        R1Converter r1Converter = getConverter();
        TJPA resourceJpa = r1Converter.toJPA(resource);
        dao.persist(resourceJpa);
        return response;
    }
 }

public class R1Converter implements Converter<R1, R1JPA>{
         @Override // come from the Converter interface
         public R1JPA toJpa(R1 object){}
}
public class R1Procedure extends AbstractProcedure<R1, R1JPA, R1Converter>{
      R1Converter converter = new R1Converter();
      public R1Converter getConverter(){
           return converter;
      }
}

Some point to consider :

  • You might want to rename your "Converter" to "Adapter"
  • Handling the database request in the same class than getting the data from the request is usually done is separated classes for separation of concerns. What if tomorrow a batch have to create entities ?
  • You can override create function to add some default value, right check and call super.create(). Though usage of super is not recommended, this is a sane usage of it IMHO.
  • "Usage of super is not recommended" .... By whom? Style guides I work to suggest that not using it is often a signifier of an error. – Jules Mar 7 '17 at 10:52
  • @Jules I did read that some time ago but I don't really remember, maybe it goes with those who prefer composition over inheritance. – Walfrat Mar 7 '17 at 12:29
2

This is a somewhat odd design. The point of inheriting is so that you don't have to have these big if blocks.

If you make the common getResourceController virtual you can then override it in the child classes and implement the class specific logic there. saving you the switch case.

ie. getResourceController(int resourceType) is inherited (and called from?) R1Procedures. resourceType is stored in the class instance

int resType = this.getResourceType(request);

so you should already have an instantiated R1Procedures which will only need to call its own branch of the getResourceController logic.

But you can probably take this further and remove the bass class altogether. Your example code has no common functionality.

What's missing from your code example is the initial input which requires you to create a class of type X. It's this entry point which is the key factor in determining how you instantiate the various objects you are going to use in your logic.

  • getResourceController() is a method which decides which implementing class to call upon. It does not have logic, it decides which implementing class instance to use based on resourceType, thus the switch case. Can you elaborate how to remove getResourceController from base?? – Siddharth Trikha Mar 7 '17 at 10:21
  • 1
    If you have a copy of Fowler et al Refactoring, see the section titled "Replace Type Code with Subclass" (page 223 in my copy). If you don't, I'd suggest getting a copy, as it's an invaluable reference. – Jules Mar 7 '17 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.