Récemment, j'essayais une entreprise «x». Ils m'ont envoyé une série de questions et m'ont dit de n'en résoudre qu'une.
Le problème est comme ça -
La taxe de vente de base est applicable à un taux de 10% sur tous les produits, à l'exception des livres, de la nourriture et des produits médicaux qui sont exonérés.
Le droit d'importation est une taxe de vente supplémentaire applicable sur toutes les marchandises importées au taux de 5%, sans exonération.
Lorsque j'achète des articles, je reçois un reçu indiquant le nom de tous les articles et leur prix (taxes comprises), en terminant par le coût total des articles et le montant total des taxes de vente payées.
Les règles d'arrondi pour la taxe de vente sont que pour un taux de taxe de n%, un prix de vente de p contient (np / 100 arrondi au 0,05 le plus proche) le montant de la taxe de vente.
«Ils m'ont dit qu'ils étaient intéressés par l' aspect conception de votre solution et qu'ils aimeraient évaluer mes compétences en programmation orientée objet .»
C'est ce qu'ils ont dit dans leurs propres mots
- Pour la solution, nous voudrions que vous utilisiez Java, Ruby ou C #.
- Nous sommes intéressés par l'ASPECT DE CONCEPTION de votre solution et souhaitons évaluer vos compétences en programmation orientée objet .
- Vous pouvez utiliser des bibliothèques ou des outils externes à des fins de création ou de test. Plus précisément, vous pouvez utiliser des bibliothèques de tests unitaires ou créer des outils disponibles pour la langue de votre choix (par exemple, JUnit, Ant, NUnit, NAnt, Test :: Unit, Rake, etc.)
- Si vous le souhaitez, vous pouvez également inclure une brève explication de votre conception et de vos hypothèses avec votre code.
- Veuillez noter que nous n'attendons PAS une application Web ou une interface utilisateur complète. Nous attendons plutôt une application simple, basée sur une console et intéressé par votre code source.
J'ai donc fourni le code ci-dessous - vous pouvez simplement copier du code et l'exécuter dans VS.
class Program
{
static void Main(string[] args)
{
try
{
double totalBill = 0, salesTax = 0;
List<Product> productList = getProductList();
foreach (Product prod in productList)
{
double tax = prod.ComputeSalesTax();
salesTax += tax;
totalBill += tax + (prod.Quantity * prod.ProductPrice);
Console.WriteLine(string.Format("Item = {0} : Quantity = {1} : Price = {2} : Tax = {3}", prod.ProductName, prod.Quantity, prod.ProductPrice + tax, tax));
}
Console.WriteLine("Total Tax : " + salesTax);
Console.WriteLine("Total Bill : " + totalBill);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
private static List<Product> getProductList()
{
List<Product> lstProducts = new List<Product>();
//input 1
lstProducts.Add(new Product("Book", 12.49, 1, ProductType.ExemptedProduct, false));
lstProducts.Add(new Product("Music CD", 14.99, 1, ProductType.TaxPaidProduct, false));
lstProducts.Add(new Product("Chocolate Bar", .85, 1, ProductType.ExemptedProduct, false));
//input 2
//lstProducts.Add(new Product("Imported Chocolate", 10, 1, ProductType.ExemptedProduct,true));
//lstProducts.Add(new Product("Imported Perfume", 47.50, 1, ProductType.TaxPaidProduct,true));
//input 3
//lstProducts.Add(new Product("Imported Perfume", 27.99, 1, ProductType.TaxPaidProduct,true));
//lstProducts.Add(new Product("Perfume", 18.99, 1, ProductType.TaxPaidProduct,false));
//lstProducts.Add(new Product("Headache Pills", 9.75, 1, ProductType.ExemptedProduct,false));
//lstProducts.Add(new Product("Imported Chocolate", 11.25, 1, ProductType.ExemptedProduct,true));
return lstProducts;
}
}
public enum ProductType
{
ExemptedProduct=1,
TaxPaidProduct=2,
//ImportedProduct=3
}
class Product
{
private ProductType _typeOfProduct = ProductType.TaxPaidProduct;
private string _productName = string.Empty;
private double _productPrice;
private int _quantity;
private bool _isImportedProduct = false;
public string ProductName { get { return _productName; } }
public double ProductPrice { get { return _productPrice; } }
public int Quantity { get { return _quantity; } }
public Product(string productName, double productPrice,int quantity, ProductType type, bool isImportedProduct)
{
_productName = productName;
_productPrice = productPrice;
_quantity = quantity;
_typeOfProduct = type;
_isImportedProduct = isImportedProduct;
}
public double ComputeSalesTax()
{
double tax = 0;
if(_isImportedProduct) //charge 5% tax directly
tax+=_productPrice*.05;
switch (_typeOfProduct)
{
case ProductType.ExemptedProduct: break;
case ProductType.TaxPaidProduct:
tax += _productPrice * .10;
break;
}
return Math.Round(tax, 2);
//round result before returning
}
}
vous pouvez désactiver l'entrée et l'exécuter pour différentes entrées.
J'ai fourni la solution mais j'ai été rejeté.
"Ils ont dit qu'ils ne pouvaient pas me considérer pour nos positions ouvertes actuelles parce que la solution de code n'est pas satisfaisante."
Veuillez me guider ce qui manque ici. Cette solution n'est-elle pas une bonne solution OOAD.
Comment puis-je améliorer mes compétences OOAD.
Mes aînés disent également qu'une application OOAD parfaite ne fonctionnera pas non plus pratiquement.
Merci
Réponses:
Tout d'abord bon Dieu, ne faites pas de calculs financiers en double . Faites des calculs financiers en décimal ; c'est à cela que ça sert. Utilisez double pour résoudre des problèmes de physique , pas des problèmes financiers .
Le principal défaut de conception de votre programme est que la politique n'est pas au bon endroit . Qui est en charge du calcul des taxes? Vous avez chargé le produit de calculer les taxes, mais lorsque vous achetez une pomme, un livre ou une machine à laver, la chose que vous vous apprêtez à acheter n'est pas responsable de vous dire sur quel montant vous allez payer. il. La politique gouvernementale est chargée de vous le dire. Votre conception viole massivement le principe de base de conception OO selon lequel les objets doivent être responsables de leurs propres préoccupations , et non de celles de quiconque. Le souci d'une machine à laver est de laver vos vêtements, pas de facturer les droits d'importation appropriés. Si les lois fiscales changent, vous ne voulez pas changerl'objet machine à laver , vous souhaitez modifier l'objet de stratégie .
Alors, comment aborder ce genre de problèmes à l'avenir?
J'aurais commencé par mettre en évidence tous les noms importants dans la description du problème:
Maintenant, quelles sont les relations entre tous ces noms?
... etc. Une fois que toutes les relations entre tous les noms ont été élaborées, vous pouvez commencer à concevoir une hiérarchie de classes. Il existe un élément de classe de base abstrait. Le livre en hérite. Il existe une classe abstraite SalesTax; BasicSalesTax en hérite. Etc.
la source
double
est idéal pour les situations où être à 0,00000001% de la bonne réponse est plus que suffisant. Si vous voulez savoir à quelle vitesse tombe une brique après une demi-seconde, faites le calcul en double. Lorsque vous effectuez un calcul financier en double, vous vous retrouvez avec des réponses comme le prix après impôt est de 43,79999999999999 dollars et cela semble ridicule même si c'est extrêmement proche de la bonne réponse.Si la société dit quelque chose à propos de bibliothèques comme NUnit, JUnit ou Test :: Unit, il est plus que probable que TDD est vraiment important pour elles. Dans votre exemple de code, il n'y a aucun test.
J'essaierais de démontrer une connaissance pratique de:
Je voudrais recommander le www.dimecasts.net comme source impressionnante de screencasts gratuits et de bonne qualité qui couvre tous les sujets mentionnés ci-dessus.
la source
C'est très subjectif, mais voici quelques points que je ferais à propos de votre code:
À mon avis, vous avez mélangé
Product
etShoppingCartItem
.Product
doit avoir le nom du produit, le statut fiscal, etc. mais pas la quantité. La quantité n'est pas une propriété d'un produit - elle sera différente pour chaque client de l'entreprise qui achète ce produit particulier.ShoppingCartItem
devrait avoir unProduct
et la quantité. De cette façon, le client peut acheter librement plus ou moins du même produit. Avec votre configuration actuelle, ce n'est pas possible.Le calcul de la taxe finale ne devrait pas non plus faire partie du
Product
- cela devrait faire partie de quelque chose comme étantShoppingCart
donné que le calcul final de la taxe peut impliquer la connaissance de tous les produits dans le panier.la source
Tout d'abord, c'est une très bonne question d'entretien. C'est un bon indicateur de nombreuses compétences.
Il y a beaucoup de choses que vous devez comprendre pour fournir une bonne réponse (il n'y a pas de réponse parfaite), à la fois de haut niveau et de bas niveau. En voici quelques-uns:
À partir de là, vous pouvez avoir de nombreuses discussions intéressantes, impliquant des principes de conception (comme les principes SOLID), des modèles de conception, des modèles d'analyse, la modélisation de domaine, des choix technologiques, des chemins d'évolution futurs (par exemple, si j'ajoute une base de données ou une couche d'interface utilisateur riche, que faut-il changer?), compromis, exigences non fonctionnelles (performances, maintenabilité, sécurité, ...), tests d'acceptation, etc ...
Je ne commenterai pas comment vous devriez changer votre solution, juste que vous devriez vous concentrer davantage sur ces concepts.
Mais, je peux vous montrer comment j'ai (partiellement) résolu ce problème , juste à titre d'exemple (en Java). Regardez dans la
Program
classe pour voir comment tout est réuni pour imprimer ce reçu:Vous devriez certainement jeter un œil à ces livres :-)
Juste une mise en garde: ma solution est encore très incomplète, je me suis juste concentré sur le scénario du chemin heureux afin d'avoir une bonne base sur laquelle bâtir.
la source
Order
imprime le reçu, maisReceipt
connaît sa propre mise en forme. En outre, TaxMethodPractice est une sorte de politique fiscale, elle contient toutes les taxes qui s'appliquent à un certain scénario. TaxMethods sont des calculateurs d'impôts. J'ai l'impression qu'il ne vous manque qu'une classe de liaison de niveau supérieur, comme votre SalesEngine proposée. C'est une idée intéressante.Sauf le fait que vous utilisez une classe appelée product, vous n'avez pas démontré que vous savez ce qu'est l'héritage, vous n'avez pas créé d'héritage à classes multiples de Product, pas de polymorphisme. Le problème aurait pu être résolu en utilisant plusieurs concepts de POO (même juste pour montrer que vous les connaissez). C'est un problème d'entretien, vous voulez donc montrer ce que vous en savez.
Je ne me transformerais cependant pas en dépression maintenant. Le fait que vous ne les ayez pas montrés ici ne signifie pas que vous ne les connaissez pas déjà ou que vous ne pouvez pas les apprendre.
Vous avez juste besoin d'un peu plus d'expérience avec la POO ou les entretiens.
Bonne chance!
la source
Les gens qui ont commencé à apprendre la programmation avec la POO n'ont pas de grands problèmes pour comprendre ce que cela signifie, car c'est comme dans la vraie vie . Si vous avez des compétences avec une autre famille de programmation que OO, cela pourrait être plus difficile à comprendre.
Tout d'abord, éteignez votre écran ou quittez votre IDE préféré. Prenez un papier et un crayon et faites une liste d' entités , de relations , de personnes , de machines , de processus , de trucs , etc. tout ce qui pourrait être rencontré dans votre programme final.
Deuxièmement, essayez d'obtenir les différentes entités de base . Vous comprendrez que certains peuvent partager des propriétés ou des capacités , il faut les mettre dans des objets abstraits . Vous devriez commencer à dessiner un joli schéma de votre programme.
Ensuite, vous devez mettre des fonctionnalités (méthodes, fonctions, sous-programmes, appelez-les comme vous le souhaitez): par exemple, un objet produit ne doit pas être capable de calculer la taxe de vente . Un objet de moteur de vente devrait.
Ne vous sentez pas mal avec tous les grands mots ( interfaces , propriétés , polymorphisme , héritage , etc.) et les modèles de conception dans un premier temps, n'essayez même pas de faire du beau code ou autre ... Pensez simplement à des objets simples et interractions entre elle comme dans la vraie vie .
Après, essayez de lire une littérature sérieuse et concise à ce sujet. Je pense que Wikipedia et Wikibooks sont un très bon moyen de commencer et de lire ensuite des informations sur GoF, les modèles de conception et UML .
la source
Premièrement, ne mélangez pas la
Product
classe avec la classe Receipt (ShoppingCart
), lequantity
devrait faire partie deReceipItem
(ShoppingCartItem
), ainsi que deTax
&Cost
. LeTotalTax
&TotalCost
devrait faire partie deShoppingCart
.Ma
Product
classe a seulementName
&Price
& quelques propriétés en lecture seule commeIsImported
:Votre partie de calcul de taxe est couplée avec
Product
. Un produit ne définit pas les politiques fiscales, c'est des classes fiscales. Selon la description du problème, il existe deux types de taxes de vente:Basic
et lesDuty
taxes. Vous pouvez utiliserTemplate Method Design Pattern
pour y parvenir:Et enfin une classe pour appliquer les taxes:
Vous pouvez les essayer sur MyFiddle .
la source
Les principes SOLID constituent un très bon point de départ pour les règles de conception .
Par exemple, le principe Open Closed stipule que si vous souhaitez ajouter de nouvelles fonctionnalités, vous n'avez pas besoin d'ajouter du code à une classe existante, mais plutôt d'ajouter une nouvelle classe.
Pour votre exemple d'application, cela signifierait que l'ajout d'une nouvelle taxe de vente nécessiterait l'ajout d'une nouvelle classe. Il en va de même pour différents produits qui font exception à la règle.
La règle d'arrondi va évidemment dans une classe distincte - le principe de responsabilité unique stipule que chaque classe a une seule responsabilité.
Je pense qu'essayer d'écrire le code vous-même apporterait beaucoup plus d'avantages que simplement écrire une bonne solution et la coller ici.
Un algorithme simple pour écrire le programme parfaitement conçu serait:
la source
Une mise en œuvre parfaite de la POO est complètement discutable. D'après ce que je vois dans votre question, vous pouvez modulariser le code en fonction du rôle qu'ils jouent pour calculer le prix final comme Product, Tax, ProductDB, etc.
Product
pourrait être une classe abstraite et les types dérivés comme Books, Food pourraient en être hérités. L'applicabilité fiscale peut être décidée par les types dérivés. Le produit indiquerait si la taxe est applicable ou non en fonction de la classe dérivée.TaxCriteria
peut être une énumération et cela peut être spécifié lors de l'achat (importé, applicabilité de la taxe de vente).Tax
class calculera la taxe en fonction deTaxCriteria
.Avoir un
ShoppingCartItem
comme suggéré par XXBBCC peut encapsuler les instances de produit et de taxe et c'est un excellent moyen de séparer les détails du produit avec la quantité, le prix total avec la taxe, etc.Bonne chance.
la source
D'un point de vue strictement OOA / D, un problème majeur que je vois est que la plupart de vos attributs de classe ont le nom redondant de la classe dans le nom d'attribut. Par exemple , le prix du produit , le type de produit . Dans ce cas, partout où vous utilisez cette classe, vous aurez un code trop verbeux et quelque peu déroutant, par exemple product.productName. Supprimez les préfixes / suffixes de nom de classe redondants de vos attributs.
De plus, je n'ai vu aucune classe concernée par l'achat et la création d'un reçu comme cela a été demandé dans la question.
la source
Voici un excellent exemple de modèle OO pour les produits, la taxe, etc. Remarquez l'utilisation d'interfaces, qui est essentielle dans la conception OO.
http://www.dreamincode.net/forums/topic/185426-design-patterns-strategy/
la source
Attaque du problème de coût avec taxe en utilisant un modèle de visiteur.
la source