CodeSOD: Extended Conditions
Every programming language embodies in it a philosophy about how problems should be solved. C reduces all problems to manipulations of memory addresses. Java turns every problem into a set of interacting objects. JavaScript summons Shub-Niggurath, the black goat of the woods with a thousand young, to eat the eyes of developers.
Just following the logic of a language can send you a long way to getting good results. Popular languages were designed by smart people, who work through many of the problems you might encounter when building a program with their tools. That doesn't mean that you can't take things a bit too far and misapply that philosophy, though.
Take this code, sent to us by "Kogad". Their co-worker understood that objects and interfaces were fundamental to Java programming, so when presented with the challenge of three conditional statements, they created this:
package com.initrode.account.framework.process.specification;import com.initrode.account.framework.process.CustomerRequest;public interface ProcesSpecification { boolean isSatisfiedBy(CustomerRequest req);}//--------------package com.initrode.account.framework.process.specification;public abstract class CompositeProcesSpecification implements ProcesSpecification { public ProcesSpecification and(ProcesSpecification specification){ return new AndProcesSpecification(this, specification); } public ProcesSpecification or(ProcesSpecification specification){ return new OrProcesSpecification(this, specification); } public ProcesSpecification not(ProcesSpecification specification){ return new NotProcesSpecification(specification); }}//--------------package com.initrode.account.framework.process.specification;import com.initrode.account.framework.process.CustomerRequest;public class NotProcesSpecification extends CompositeProcesSpecification { private ProcesSpecification spec; public NotProcesSpecification(ProcesSpecification specification) { spec = specification; } @Override public boolean isSatisfiedBy(CustomerRequest req) { return !spec.isSatisfiedBy(req); }}//--------------package com.initrode.account.framework.process.specification;import com.initrode.account.framework.process.CustomerRequest;public class AndProcesSpecification extends CompositeProcesSpecification { private ProcesSpecification specOne; private ProcesSpecification specTwo; public AndProcesSpecification(ProcesSpecification specificationOne, ProcesSpecification specificationTwo) { specOne = specificationOne; specTwo = specificationTwo; } @Override public boolean isSatisfiedBy(CustomerRequest req) { return specOne.isSatisfiedBy(req) && specTwo.isSatisfiedBy(req); }}//--------------package com.initrode.account.framework.process.specification;import com.initrode.account.framework.process.CustomerRequest;public class OrProcesSpecification extends CompositeProcesSpecification { private ProcesSpecification specOne; private ProcesSpecification specTwo; public OrProcesSpecification(ProcesSpecification specificationOne, ProcesSpecification specificationTwo) { specOne = specificationOne; specTwo = specificationTwo; } @Override public boolean isSatisfiedBy(CustomerRequest req) { return specOne.isSatisfiedBy(req) || specTwo.isSatisfiedBy(req); }}//--------------package com.initrode.account.framework.process.specification;import com.initrode.account.framework.process.CustomerRequest;import com.initrode.account.framework.process.CustomerType;public class TypeOneProcesSpecification extends CompositeProcesSpecification { @Override public boolean isSatisfiedBy(CustomerRequest req) { return null != req && CustomerType.ONE == req.getType(); }}//--------------package com.initrode.account.framework.process.specification;import com.initrode.account.framework.process.CustomerRequest;import com.initrode.account.framework.process.CustomerType;public class TypeTwoProcesSpecification extends CompositeProcesSpecification { @Override public boolean isSatisfiedBy(CustomerRequest req) { return null != req && CustomerType.TWO == req.getType(); }}//--------------package com.initrode.account.framework.process.specification;import com.initrode.account.framework.process.CustomerRequest;public class VerifyProcessSpecification extends CompositeSpecification @Override public boolean isSatisfiedBy(CustomerRequest req) { return req.hasVerificationCode(); }}//--------------// Usage:public class ActionOne { private ProcesSpecification procesSpec; @PostConstruct protected void postInitialize() { setProcesSpecification(new VerifyProcessSpecification().and(new TypeOneProcesSpecification())); } @Override public boolean canHandle(CustomerRequest req) { return procesSpec.isSatisfiedBy(req); } @Override void doAction(...);}public class ActionTwo { private ProcesSpecification procesSpec; @PostConstruct protected void postInitialize() { setProcesSpecification(new VerifyProcessSpecification().and(new TypeTwoProcesSpecification())); } @Override public boolean canHandle(CustomerRequest req) { return procesSpec.isSatisfiedBy(req); } @Override void doAction(...);}public class ActionThree { private ProcesSpecification procesSpec; @PostConstruct public void postInitialize() { procesSpec = new NotProcesSpecification(new VerifyProcessSpecification().and( new TypeOneProcesSpecification().or(new TypeTwoProcesSpecification()))); } @Override public boolean canHandle(CustomerRequest req) { return procesSpec.isSatisfiedBy(req); } @Override void doAction(...);}
This is certainly Peak Javaa. It's" extensible, at least. Not that you'd want to. "Kogad" replaced this masterpiece with a much simpler, if less extensible, chain of conditionals that were also more closely mapped to their actual requirements.
[Advertisement] Otter enables DevOps best practices by providing a visual, dynamic, and intuitive UI that shows, at-a-glance, the configuration state of all your servers. Find out more and download today!