Test de programmation Java pour interview


Voici un test de programmation utilisé dans un entretien d'embauche. Je trouve qu'il a une perspective non-OO très étrange et je me demande pourquoi quelqu'un approcherait un constructeur de cette perspective. En tant que programmeur Java très expérimenté, je questionne immédiatement 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 interviews. J'aimerais les commentaires d'autres Java OO expérimentés programmeur.

Terminez le constructeur du solveur de sorte qu'un appel à solveAll renvoie une liste avec 2 valeurs y compris 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<MathFunction> functionList;

    public Solver() { 

        //Complete here

    }

    public List<Double> solveAll(double x) {
        List<Double> result = new ArrayList<Double>();
        for (MathFunction function : this.functionList) {
            result.add(new Double(function.calculate(x)));
        }

        return result;
    }
} 
Author: Andrew Barber, 2012-08-21

9 answers

Il s'agit de tester 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 comportemental). Voir ces:

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

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

Si vous allez pour un entretien Java, vous devriez être en mesure d'identifier le modèle de conception auquel ils font allusion et cela devrait vous éviter d'être trop perturbé!

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

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

 37
Author: Joe, 2012-08-21 15:01:49

Je suis d'accord que c'est déroutant et sur-conçu.

Mais je pense que le code est raisonnablement orienté objet. C'est une instance du modèle de stratégie. Le code qui génère une liste de réponses ne se soucie pas de la façon dont les réponses sont calculées - les deux préoccupations sont séparées et une stratégie de calcul différente pourrait être appliquée sans avoir à toucher le code qui génère la liste.

Pour rendre la classe plus utile, ces fonctions doivent être transmises depuis le en dehors (c'est-à-dire injection de dépendance) plutôt que d'être instancié dans le constructeur.

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

public Solver() {
    functionList = new ArrayList<MathFunction>();

    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);
        }
    });
}
 31
Author: ᴇʟᴇvᴀтᴇ, 2012-08-23 15:04:55

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

Je dirais qu'une approche beaucoup plus agréable serait d'avoir une méthode addMathFunction(MathFunction mf). Et si vous le souhaitez, créez des sous-classes qui étendent la classe Solver et ajoutent des fonctions mathématiques dans leur constructeur.

 6
Author: Martijn Courteaux, 2012-08-21 14:53:18

Je pense qu'ils voulaient que vous ajoutiez deux éléments dans la functionlist. Chacun implémenterait l'interface MathFunction, une pour la racine carrée et une pour l'inverse. Le prboblem réside dans les détails:

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

2-Si vous voulez avoir cette classe "do-it-all", m il serait intéressant de recevoir les Mathfunctions en tant que paramètre afin que vous puissiez faire n'importe quelle sorte de MathFunctions, les MathFunctions serait paramétrable

 3
Author: JSBach, 2012-08-21 14:53:36

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

public Solver() { 
    functionList = new ArrayList<MathFunction>();
    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.
  • Si le programmeur comprend que les instances d'interfaces ou de classes peuvent être stockées dans une liste, et itérées plus tard.
 3
Author: Gilbert Le Blanc, 2012-08-21 15:17:06

Bien que je convienne que ce n'est probablement pas la meilleure façon, ou la façon la plus OO de le faire, je devrais supposer que le but de cet exercice est de voir à quel point vous comprenez l'héritage, les Interfaces et peut-être les classes internes anonymes. C'est la seule chose que je peux comprendre.

 3
Author: Jason Carter, 2012-08-21 18:07:18

Ok, j'ai codé la solution à ma propre question. Mon instinct que rien ne devrait être dans le constructeur semble être correct. La liste de fonctions n'est pas statique, vous avez donc besoin d'une instance pour l'initialiser. Il spécifie entier donc j'arrondis à entier. La fonction inverse n'est en aucun cas avancée en mathématiques.

import java.util.ArrayList;
import java.util.List;
import java.lang.Math;

public class Solver {

    private List<MathFunction> functionList = new ArrayList<MathFunction>();;

    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<Double> solveAll(double x) {
        List<Double> result = new ArrayList<Double>();

        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(String[] 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);

    }
 3
Author: user916115, 2012-08-22 03:46:47

Quelque peu artificiel, me semble plus proche du motif décorateur. Je ne sais pas ce que je dirais lors d'une interview mais voici comment je le coderais:

package math;

import java.util.ArrayList;
import java.util.List;

public class DecoratorMath 
{

    interface MathFunction 
    {
        double calculate(double x);
    }

    public static void main(String[] args) 
    {
        DecoratorMath decoratorMath =  new DecoratorMath();
        decoratorMath.go();
    }

    public void go() 
    {
        Solver solver = new Solver();
        decorate(solver);
        List<Double> 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<MathFunction> mathFunctions = new ArrayList<MathFunction>();

        public void addFunction(MathFunction mathFunction)
        {
            mathFunctions.add(mathFunction);
        }

        public List<Double> solveAll(double x) 
        {
            List<Double> result = new ArrayList<Double>();
            for (MathFunction function : mathFunctions) 
            {
                result.add(new Double(function.calculate(x)));
            }
            return result;
        }
    }
}
 2
Author: Bob, 2013-01-06 02:15:32

Faire tout cela dans le constructeur est juste 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<MathFunction> 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>();

    MathFunction f =  (MathFunction) new X();
    functionList.add(f);  

    MathFunction f2 =  (MathFunction) new Y();
    functionList.add(f2);

  }


  public List<Double> solveAll(double x){ 

  List<Double> result=new ArrayList<Double>();

    for (MathFunction function : this.functionList){

      result.add(new Double(function.calculate(x)));

    }

    return result;

  }

public static void main(String... args) {

    System.out.println("result="+new Solver().solveAll(123));

}

}
 0
Author: , 2015-01-09 23:48:24