Kürzlich habe ich versucht, eine Firma 'x'. Sie schickten mir einige Fragen und sagten mir, ich solle nur eine lösen.
Das Problem ist wie folgt:
Die Grundumsatzsteuer beträgt 10% für alle Waren, ausgenommen Bücher, Lebensmittel und Medizinprodukte, die davon ausgenommen sind.
Der Einfuhrzoll ist eine zusätzliche Umsatzsteuer, die auf alle eingeführten Waren in Höhe von 5% ohne Ausnahmen erhoben wird.
Wenn ich Artikel kaufe, erhalte ich eine Quittung, in der der Name aller Artikel und deren Preis (einschließlich Steuern) aufgeführt sind, die mit den Gesamtkosten der Artikel und den Gesamtbeträgen der gezahlten Umsatzsteuern endet.
Die Rundungsregeln für die Umsatzsteuer lauten, dass bei einem Steuersatz von n% ein Regalpreis von p (np / 100 auf die nächste 0,05 aufgerundet) Umsatzsteuerbetrag enthält.
"Sie sagten mir, sie interessieren sich für den Designaspekt Ihrer Lösung und möchten meine objektorientierten Programmierkenntnisse bewerten ."
Das sagten sie in ihren eigenen Worten
- Für die Lösung möchten wir, dass Sie entweder Java, Ruby oder C # verwenden.
- Wir interessieren uns für den DESIGN-ASPEKT Ihrer Lösung und möchten Ihre objektorientierten Programmierkenntnisse bewerten .
- Sie können externe Bibliotheken oder Tools zum Erstellen oder Testen verwenden. Insbesondere können Sie Unit-Test-Bibliotheken verwenden oder Tools erstellen, die für die von Ihnen ausgewählte Sprache verfügbar sind (z. B. JUnit, Ant, NUnit, NAnt, Test :: Unit, Rake usw.).
- Optional können Sie Ihrem Code auch eine kurze Erläuterung Ihres Designs und Ihrer Annahmen hinzufügen.
- Bitte beachten Sie, dass wir KEINE webbasierte Anwendung oder eine umfassende Benutzeroberfläche erwarten. Vielmehr erwarten wir eine einfache, konsolenbasierte Anwendung, die sich für Ihren Quellcode interessiert.
Also habe ich unten Code bereitgestellt - Sie können einfach Code einfügen und in VS ausführen.
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
}
}
Sie können die Eingabe trennen und für verschiedene Eingaben ausführen.
Ich lieferte die Lösung, wurde aber abgelehnt.
"Sie sagten, sie können mich nicht für unsere derzeit offenen Positionen in Betracht ziehen, weil die Codelösung nicht zufriedenstellend ist."
Bitte leiten Sie mich, was hier fehlt. Ist diese Lösung keine gute OOAD-Lösung?
Wie kann ich meine OOAD-Fähigkeiten verbessern?
Meine Senioren sagen auch, dass eine perfekte OOAD-Anwendung auch praktisch nicht funktioniert.
Vielen Dank
Antworten:
Zunächst einmal macht der Himmel keine doppelten Finanzberechnungen . Führen Sie Finanzberechnungen in Dezimalzahlen durch . dafür ist es da. Verwenden Sie double, um physikalische Probleme zu lösen , nicht finanzielle Probleme.
Der größte Konstruktionsfehler in Ihrem Programm besteht darin, dass die Richtlinie am falschen Ort ist . Wer ist für die Berechnung der Steuern verantwortlich? Sie haben das Produkt mit der Berechnung der Steuern beauftragt, aber wenn Sie einen Apfel, ein Buch oder eine Waschmaschine kaufen, ist das, was Sie kaufen möchten, nicht dafür verantwortlich, Ihnen mitzuteilen, wie viel Steuern Sie bezahlen werden es. Die Regierungspolitik ist dafür verantwortlich, Ihnen dies mitzuteilen. Ihr Design verstößt massiv gegen das grundlegende OO-Designprinzip, wonach Objekte für ihre eigenen Anliegen verantwortlich sein sollten und nicht für die anderer. Das Anliegen einer Waschmaschine ist es, Ihre Kleidung zu waschen und nicht den richtigen Einfuhrzoll zu erheben. Wenn sich die Steuergesetze ändern, möchten Sie sich nicht ändernAls Waschmaschinenobjekt möchten Sie das Richtlinienobjekt ändern .
Wie können wir diese Art von Problemen in Zukunft angehen?
Ich hätte damit begonnen, jedes wichtige Substantiv in der Problembeschreibung hervorzuheben:
Welche Beziehungen bestehen zwischen all diesen Substantiven?
... und so weiter. Sobald Sie alle Beziehungen zwischen allen Substantiven ausgearbeitet haben, können Sie mit dem Entwerfen einer Klassenhierarchie beginnen. Es gibt eine abstrakte Basisklasse Item. Buch erbt davon. Es gibt eine abstrakte Klasse SalesTax; BasicSalesTax erbt davon. Und so weiter.
quelle
double
Ideal für Situationen, in denen es mehr als ausreichend ist, innerhalb von 0,00000001% der richtigen Antwort zu liegen. Wenn Sie herausfinden möchten, wie schnell ein Stein nach einer halben Sekunde fällt, rechnen Sie im Doppel. Wenn Sie Finanz- Arithemik im Doppel durchführen, erhalten Sie Antworten wie den Preis nach Steuern von 43,79999999999999 US-Dollar, und das sieht einfach albern aus, obwohl es der richtigen Antwort sehr nahe kommt.Wenn das Unternehmen etwas über Bibliotheken wie NUnit, JUnit oder Test :: Unit erzählt, ist es mehr als wahrscheinlich, dass TDD für sie wirklich wichtig ist. In Ihrem Codebeispiel gibt es überhaupt keine Tests.
Ich würde versuchen, praktisches Wissen zu demonstrieren über:
Ich möchte das www.dimecasts.net als beeindruckende Quelle für kostenlose Screencasts von guter Qualität empfehlen, die alle oben genannten Themen abdecken.
quelle
Dies ist sehr subjektiv, aber hier sind einige Punkte, die ich zu Ihrem Code machen möchte:
Meiner Meinung nach haben Sie gemischt
Product
undShoppingCartItem
.Product
sollte den Produktnamen, den Steuerstatus usw. haben, aber nicht die Menge. Die Menge ist keine Eigenschaft eines Produkts - sie ist für jeden Kunden des Unternehmens, der dieses bestimmte Produkt kauft, unterschiedlich.ShoppingCartItem
sollte eineProduct
und die Menge haben. Auf diese Weise kann der Kunde mehr oder weniger des gleichen Produkts frei kaufen. Mit Ihrem aktuellen Setup ist das nicht möglich.Die Berechnung der endgültigen Steuer sollte auch nicht Teil von sein
Product
- es sollte Teil von so etwas sein,ShoppingCart
da die endgültige Steuerberechnung möglicherweise die Kenntnis aller Produkte im Warenkorb beinhaltet.quelle
Zunächst einmal ist dies eine sehr gute Interviewfrage. Es ist ein gutes Maß für viele Fähigkeiten.
Es gibt viele Dinge, die Sie verstehen müssen, um eine gute Antwort zu geben (es gibt keine perfekte Antwort), sowohl auf hoher als auch auf niedriger Ebene. Hier sind ein paar:
Von dort aus können Sie viele interessante Diskussionen führen, die Entwurfsprinzipien (wie die SOLID-Prinzipien), Entwurfsmuster, Analysemuster, Domänenmodellierung, Technologieoptionen und zukünftige Entwicklungspfade umfassen (z. B. was ist, wenn ich eine Datenbank oder eine umfangreiche UI-Ebene hinzufüge). Was muss geändert werden?), Kompromisse, nicht funktionale Anforderungen (Leistung, Wartbarkeit, Sicherheit, ...), Abnahmetests usw.
Ich werde nicht kommentieren, wie Sie Ihre Lösung ändern sollten, nur dass Sie sich mehr auf diese Konzepte konzentrieren sollten.
Aber ich kann Ihnen nur als Beispiel (in Java) zeigen, wie ich dieses Problem (teilweise) gelöst habe . Schauen Sie in der
Program
Klasse nach, wie alles zusammenkommt, um diese Quittung auszudrucken:Sie sollten sich unbedingt diese Bücher ansehen :-)
Nur als Einschränkung: Meine Lösung ist immer noch sehr unvollständig. Ich habe mich nur auf das Happy-Path-Szenario konzentriert, um eine gute Grundlage zu haben, auf der ich aufbauen kann.
quelle
Order
die Quittung aus,Receipt
kennt aber die eigene Formatierung. Außerdem ist TaxMethodPractice eine Art Steuerrichtlinie, die alle Steuern enthält, die für ein bestimmtes Szenario gelten. TaxMethods sind Steuerrechner. Ich habe das Gefühl, dass Ihnen nur eine höhere Bindungsklasse fehlt , wie Ihre vorgeschlagene SalesEngine. Das ist eine interessante Idee.Abgesehen von der Tatsache, dass Sie eine Klasse namens Produkt verwenden, haben Sie nicht nachgewiesen, dass Sie wissen, was Vererbung ist. Sie haben keine mehrfach klassifizierte Vererbung von Produkt erstellt, keinen Polymorphismus. Das Problem hätte mit mehreren OOP-Konzepten gelöst werden können (auch um zu zeigen, dass Sie sie kennen). Dies ist ein Interviewproblem, daher möchten Sie zeigen, wie viel Sie wissen.
Ich würde mich jetzt jedoch nicht in eine Depression verwandeln. Die Tatsache, dass Sie sie hier nicht demonstriert haben, bedeutet nicht, dass Sie sie noch nicht kennen oder nicht lernen können.
Sie brauchen nur etwas mehr Erfahrung mit OOP oder Interviews.
Viel Glück!
quelle
Menschen, die mit OOP angefangen haben, Programmieren zu lernen, haben keine großen Probleme zu verstehen, was es bedeutet, weil es genauso ist wie im wirklichen Leben . Wenn Sie mit anderen Programmierkenntnissen als OO vertraut sind, ist dies möglicherweise schwieriger zu verstehen.
Schalten Sie zunächst Ihren Bildschirm aus oder beenden Sie Ihre Lieblings-IDE. Nehmen Sie ein Papier und einen Bleistift und machen Sie eine Liste von Entitäten , Beziehungen , Menschen , Maschinen , Prozesse , Material usw. alles , die in Ihr endgültiges Programm begegnet werden könnten.
Zweitens versuchen Sie, die verschiedenen grundlegenden Entitäten zu erhalten. Sie werden verstehen, dass einige Eigenschaften oder Fähigkeiten gemeinsam nutzen können. Sie müssen sie in abstrakte Objekte einfügen . Sie sollten beginnen, ein schönes Schema Ihres Programms zu zeichnen.
Als nächstes müssen Sie Funktionen (Methoden, Funktionen, Unterprogramme, wie gewünscht aufrufen) eingeben: Beispielsweise sollte ein Produktobjekt nicht in der Lage sein, die Umsatzsteuer zu berechnen . Ein Sales Engine Objekt sollte.
Machen Sie beim ersten Mal keine Probleme mit all den großen Wörtern ( Schnittstellen , Eigenschaften , Polymorphismus , Erbe usw.) und Designmustern. Versuchen Sie nicht einmal, schönen Code oder was auch immer zu erstellen. Denken Sie nur an einfache Objekte und Wechselwirkungen zwischen ihm wie im wirklichen Leben .
Versuchen Sie anschließend, eine ernsthafte, prägnante Literatur darüber zu lesen. Ich denke, Wikipedia und Wikibooks sind ein wirklich guter Weg, um zu beginnen und dann einfach etwas über GoF und Design Patterns und UML zu lesen .
quelle
Mischen Sie zuerst keine
Product
Klasse mit der Receipt (ShoppingCart
) - Klasse, diequantity
sollte Teil vonReceipItem
(ShoppingCartItem
) sein, sowieTax
&Cost
. DasTotalTax
&TotalCost
sollte ein Teil von seinShoppingCart
.Meine
Product
Klasse hat nurName
&Price
& einige schreibgeschützte Eigenschaften wieIsImported
:Ihr Steuerberechnungsteil ist gekoppelt mit
Product
. Ein Produkt definiert keine Steuerrichtlinien, sondern Steuerklassen. Basierend auf der Beschreibung des Problems gibt es zwei Arten von Umsatzsteuern:Basic
undDuty
Steuern. Sie können verwendenTemplate Method Design Pattern
, um es zu erreichen:Und schließlich eine Klasse, um Steuern anzuwenden:
Sie können sie bei MyFiddle ausprobieren .
quelle
Ein sehr guter Ausgangspunkt für Entwurfsregeln sind die SOLID- Prinzipien.
Das Open Closed-Prinzip besagt beispielsweise, dass Sie, wenn Sie neue Funktionen hinzufügen möchten, der vorhandenen Klasse keinen Code hinzufügen müssen, sondern eine neue Klasse hinzufügen müssen.
Für Ihre Beispielanwendung würde dies bedeuten, dass für das Hinzufügen einer neuen Umsatzsteuer eine neue Klasse hinzugefügt werden muss. Gleiches gilt für verschiedene Produkte, die Ausnahmen von der Regel darstellen.
Die Rundungsregel gilt offensichtlich für eine separate Klasse - das Prinzip der Einzelverantwortung besagt, dass jede Klasse eine Einzelverantwortung hat.
Ich denke, der Versuch, den Code selbst zu schreiben, würde weitaus mehr Nutzen bringen, als einfach eine gute Lösung zu schreiben und sie hier einzufügen.
Ein einfacher Algorithmus zum Schreiben des perfekt gestalteten Programms wäre:
quelle
Eine perfekte OOP-Implementierung ist völlig umstritten. Nach dem, was ich in Ihrer Frage sehe, können Sie den Code basierend auf der Rolle, die sie für die Berechnung des Endpreises wie Produkt, Steuer, ProduktDB usw. spielen, modularisieren.
Product
könnte eine abstrakte Klasse sein und die abgeleiteten Typen wie Bücher, Lebensmittel könnten davon geerbt werden. Die steuerliche Anwendbarkeit kann durch die abgeleiteten Typen entschieden werden. Das Produkt würde anhand der abgeleiteten Klasse feststellen, ob die Steuer anwendbar ist oder nicht.TaxCriteria
kann eine Aufzählung sein und diese kann während des Kaufs angegeben werden (importiert, Anwendbarkeit der Umsatzsteuer).Tax
Klasse berechnet Steuern basierend aufTaxCriteria
.Mit einem
ShoppingCartItem
von XXBBCC vorgeschlagenen Wert können Produkt- und Steuerinstanzen gekapselt werden. Dies ist eine hervorragende Möglichkeit, Produktdetails nach Menge, Gesamtpreis nach Steuern usw. zu trennen.Viel Glück.
quelle
Aus einer rein OOA / D-Perspektive ist ein Hauptproblem, das ich sehe, dass die meisten Ihrer Klassenattribute den redundanten Namen der Klasse im Attributnamen haben. zB Produkt Preis, typeOf Produkt . In diesem Fall haben Sie überall dort, wo Sie diese Klasse verwenden, übermäßig ausführlichen und etwas verwirrenden Code, z. B. product.productName. Entfernen Sie das redundante Klassennamenpräfix / -suffix aus Ihren Attributen.
Außerdem habe ich keine Klassen gesehen, die sich mit dem Kauf und der Erstellung einer Quittung befassten, wie in der Frage gestellt.
quelle
Hier ist ein großartiges Beispiel für ein OO-Muster für Produkte, Steuern usw. Beachten Sie die Verwendung von Schnittstellen, die für das OO-Design unerlässlich sind.
http://www.dreamincode.net/forums/topic/185426-design-patterns-strategy/
quelle
Das Problem mit den Kosten mit Steuern wurde mithilfe eines Besuchermusters angegriffen.
quelle