Test de programmation Java pour l’interview

Voici un test de programmation utilisé dans un entretien d’embauche. Je trouve que cela a un sharepoint vue non-OO très étrange et je me demande pourquoi quelqu’un pourrait approcher un constructeur de cette perspective. En tant que programmeur Java très expérimenté, je remets immédiatement en question la capacité de l’individu qui a écrit ce code et la perspective étrange de la question.

Je trouve troublantes ces étranges questions hors contexte sur les entretiens. Je serais ravi des commentaires d’autres programmeurs Java OO expérimentés.

Complétez le constructeur Solver pour qu’un appel à solveAll renvoie une liste de 2 valeurs incluant la racine carrée et l’inverse de l’entier passé en paramètre.

public interface MathFunction { double calculate(double x); } public class Solver { private List functionList; public Solver() { //Complete here } public List solveAll(double x) { List result = new ArrayList(); for (MathFunction function : this.functionList) { result.add(new Double(function.calculate(x))); } return result; } } 

Cela teste vos modèles de conception, en utilisant la méthode la plus simple possible. Je pense que cela pourrait être la stratégie (ou un autre modèle de comportement). Voir ces:

http://en.wikipedia.org/wiki/Strategy_pattern

http://en.wikipedia.org/wiki/Behavioral_pattern

Si vous envisagez un entretien avec Java, vous devriez être en mesure d’identifier le modèle de conception auquel ils font allusion et qui devrait vous empêcher d’être trop perturbé!

Pour répondre à la question, créez deux classes qui implémentent MathFunction , puis créez deux instances et stockez-les dans functionList .

Le point ici n’est pas “pouvez-vous faire des calculs de cette manière étrange”, c’est “pouvez-vous identifier des modèles de conception”.

Je suis d’accord que c’est déroutant et trop d’ingénierie.

Mais je pense que le code est raisonnablement orienté object. C’est une instance du modèle de stratégie. Le code qui génère une liste de réponses ne tient pas compte de la manière dont les réponses sont calculées – les deux problèmes sont séparés et une stratégie de calcul différente peut être appliquée sans avoir à toucher le code qui génère la liste.

Pour rendre la classe plus utile, ces fonctions devraient être passées de l’extérieur (c.-à-d. L’dependency injection) plutôt que d’être instanciées dans le constructeur.

Vous connaissez la réponse, je suppose, mais pour ce que ça vaut …

 public Solver() { functionList = new ArrayList(); functionList.add(new MathFunction() { @Override public double calculate(double x) { return 1d/x; } }); functionList.add(new MathFunction() { @Override public double calculate(double x) { return Math.sqrt(x); } }); } 

IMHO, c’est en effet une approche étrange. Le nom Solver est générique, il ne devrait pas implémenter d’opérations spécifiques par défaut. Cependant, peut-être que cela faisait partie de l’interview? Première partie: remplissez simplement la demande. Deuxième partie: dites que c’est étrange de le faire.

Je dirais qu’une approche beaucoup plus addMathFunction(MathFunction mf) serait d’avoir une addMathFunction(MathFunction mf) . Et si vous le souhaitez, créer des sous-classes qui étendent la classe Solver et append des fonctions MathFunctions dans leur constructeur.

Je pense qu’ils voulaient que vous ajoutiez deux éléments dans la liste des fonctions. Chacun implémenterait l’interface MathFunction, un pour la racine carrée et un pour l’inverse. Le problème réside dans les détails:

1- Vous avez une fonction qui renvoie 2 valeurs car elle fait deux choses différentes, c’est mal

2- Si vous voulez avoir cette classe “do-it-all”, il serait intéressant de recevoir les Mathfunctions en tant que paramètre pour pouvoir effectuer n’importe quelle sorte de MathFunctions, les MathFunctions étant paramétrables

Voici ma solution Ceci est une illustration simple d’une classe d’usine .

 public Solver() { functionList = new ArrayList(); MathFunction sqrt = new MathFunction() { @Override public double calculate(double x) { return Math.sqrt(x); } }; functionList.add(sqrt); MathFunction inverse = new MathFunction() { @Override public double calculate(double x) { return 1.0D / x; } }; functionList.add(inverse); } 

Cette question montre deux choses:

  • Si le programmeur comprend des termes mathématiques comme inverse.
  • Indique si le programmeur comprend que des instances d’interfaces ou de classes peuvent être stockées dans une liste et itérées ultérieurement.

Bien que je sois d’accord sur le fait que ce n’est probablement pas le meilleur moyen, ou la plupart des méthodes OO, je devrais supposer que le but de cet exercice est de voir comment vous comprenez l’inheritance, les interfaces et peut-être les classes internes anonymes. C’est la seule chose que je peux comprendre.

Ok, j’ai codé la solution à ma propre question. Mon instinct que rien ne devrait être dans le constructeur semble être correct. La fonctionList n’est pas statique, vous avez donc besoin d’une instance pour l’initialiser. Il spécifie un entier donc je arrondis à un entier. La fonction inverse n’est pas une mathématique avancée.

 import java.util.ArrayList; import java.util.List; import java.lang.Math; public class Solver { private List functionList = new ArrayList();; public Solver() { // Complete here } public void initFunctionList() { MathFunction functionSquareRoot = new MathFunction(){ @Override public double calculate(double x) { return (x<0 ? 0: Math.sqrt(x)); // maybe we need throw an exception here for negative numbers, but we'll just set it to 0 }}; MathFunction functionInverse = new MathFunction(){ @Override public double calculate(double x) { return (x!=0.0 ? 1/x : 0); } }; functionList.add(functionSquareRoot); functionList.add(functionInverse); } public List solveAll(double x) { List result = new ArrayList(); for (MathFunction function : this.functionList) { result.add(new Double(function.calculate(x))); } return result; } } public interface MathFunction { double calculate(double x); } public class TestSolver { /** * @param args */ public static void main(Ssortingng[] args) { Solver s = new Solver(); s.initFunctionList(); System.out.println(s.solveAll(16.0)); } } 

Je me trompe le constructeur peut être

 public Solver() { // Complete here MathFunction functionSquareRoot = new MathFunction(){ @Override public double calculate(double x) { return (x<0 ? 0: Math.sqrt(x)); // maybe we need throw an exception here for negative numbers, but we'll just set it to 0 }}; MathFunction functionInverse = new MathFunction(){ @Override public double calculate(double x) { return (x!=0.0 ? 1/x : 0); } }; functionList.add(functionSquareRoot); functionList.add(functionInverse); } 

Un peu artificiel, me semble plus proche du modèle de décorateur. Je ne suis pas sûr de ce que je dirais pendant une interview, mais voici comment je coderais:

 package math; import java.util.ArrayList; import java.util.List; public class DecoratorMath { interface MathFunction { double calculate(double x); } public static void main(Ssortingng[] args) { DecoratorMath decoratorMath = new DecoratorMath(); decoratorMath.go(); } public void go() { Solver solver = new Solver(); decorate(solver); List results = solver.solveAll(02); for (Double d :results) { System.out.println(d); } } public void decorate(Solver solver) { solver.addFunction(new MathFunction() { @Override public double calculate(double x) { return Math.sqrt(x); } }); solver.addFunction(new MathFunction() { @Override public double calculate(double x) { return 1d/x; } }); } class Solver { private List mathFunctions = new ArrayList(); public void addFunction(MathFunction mathFunction) { mathFunctions.add(mathFunction); } public List solveAll(double x) { List result = new ArrayList(); for (MathFunction function : mathFunctions) { result.add(new Double(function.calculate(x))); } return result; } } } 

Faire tout cela au sein du constructeur n’est qu’une mauvaise pratique. Quoi qu’il en soit, ma solution tout-en-un.

 import java.util.*; import java.math.*; //sqrt / inverse public class Solver{ private List functionList; public interface MathFunction{ double calculate(double x); } class X implements MathFunction { public double calculate(double x) { return Math.sqrt(x); } } class Y implements MathFunction { public double calculate(double y) { return 1/y; } } public Solver(){ //here functionList = new ArrayList(); MathFunction f = (MathFunction) new X(); functionList.add(f); MathFunction f2 = (MathFunction) new Y(); functionList.add(f2); } public List solveAll(double x){ List result=new ArrayList(); for (MathFunction function : this.functionList){ result.add(new Double(function.calculate(x))); } return result; } public static void main(Ssortingng... args) { System.out.println("result="+new Solver().solveAll(123)); } }