Skip to content

Commit 231279d

Browse files
committed
2 parents b7b7071 + b522ef1 commit 231279d

12 files changed

+174
-0
lines changed

Topics/07. OOP-Workshop/README.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
![logo](https://raw.githubusercontent.com/TelerikAcademy/Common/master/logos/telerik-header-logo.png)
2+
## Cosmetics shop - workshop
3+
4+
### Description
5+
In the shop there are currently two types of **products: shampoos** and **toothpastes**. Each product has **name, brand, price and gender** (men, women, unisex). Each **shampoo** has **quantity** (in milliliters) and **usage** (every day or medical). All shampoos’ price is per milliliter. Toothpastes have **ingredients**. There are **categories** of products. Each **category** has **name** and products can be **added or removed**. The same product can be added to a category more than once. There is also a **shopping cart**. Products can be **added or removed** from it. The same product can be added to the shopping cart more than once. The shopping cart can calculate the **total price** of all products in it.
6+
7+
### Task
8+
Your **task** is to **design an object-oriented class hierarchy** to model the cosmetics shop, **using the best practices for object-oriented design** (OOD) and **object-oriented programming** (OOP). **Avoid** duplicated code though abstraction, inheritance, and polymorphism and encapsulate correctly all fields.
9+
10+
You are given few C# interfaces that you should **obligatory** implement and use as a basis of your code:
11+
12+
#### 1. Categories should implement ICategory.
13+
- Adding the same product to one category more than once is allowed.
14+
- Minimum category name’s length length is 2 symbols and maximum is 15 symbols.
15+
- The error message should be **"Category name must be between {min} and {max} symbols long!""**.
16+
- Products in category should be sorted by brand in ascending order and then by price in descending order.
17+
- When removing product from category, if the product is not found, the error message should be **"Product {product name} does not exist in category {category name}!""**.
18+
- Category’s print method should return text in the following format:
19+
20+
21+
```
22+
{category name} category – {number of products} products/product in total
23+
- {product brand} – {product name}:
24+
* Price: ${product price}
25+
* For gender: Men/Women/Unisex
26+
* Ingredients: {product ingredients, separated by “, “} (when applicable)
27+
- {product brand} – {product name}:
28+
* Price: ${product price}
29+
* For gender: {product gender}
30+
* Quantity: {product quantity} ml (when applicable)
31+
* Usage: EveryDay/Medical (when applicable)
32+
```
33+
34+
#### 2. All products should implement the IProduct interface.
35+
- Minimum product name’s length is 3 symbols and maximum is 10 symbols.
36+
- The error message should be **"Product name must be between {min} and {max} symbols long!"**.
37+
- Minimum brand name’s length is 2 symbols and maximum is 10 symbols.
38+
- The error message should be **"Product brand must be between {min} and {max} symbols long!"**.
39+
- Gender type can be **"Men"**, **"Women"** or **"Unisex"**.
40+
41+
#### 3. All shampoos should implement the IShampoo interface.
42+
43+
#### 4. All toothpastes should implement the **IToothpaste** interface.
44+
- Ingredients should be represented as text, joined in their order of addition, separated by ", " (comma and space).
45+
- Each ingredient name’s length should be between 4 and 12 symbols, inclusive. The error message should be **"Each ingredient must be between {min} and {max} symbols long!"**.
46+
47+
#### 5. Shopping cart.
48+
- Adding the same product more than once is allowed.
49+
- Do not check if the product exists, when removing it from the shopping cart.
50+
51+
52+
### Constraints
53+
- Look into the example below to get better understanding of the printing format.
54+
- All number type fields should be printed “as is”, without any formatting or rounding.
55+
- All properties in the above interfaces are mandatory (cannot be null or empty).
56+
- If a null value is passed to some mandatory property, your program should throw a proper exception.
57+
58+
### Additional notes
59+
- To simplify your work you are given an already built execution engine that executes a sequence of commands read from the console using the classes and interfaces in your project (see the Cosmetics-Skeleton folder).
60+
- Please, put your classes in namespace Cosmetics.Products.
61+
- Implement the CosmeticsFactory class in the namespace Cosmetics.Engine.
62+
- You are **only allowed** to write classes and **extract appropriate interfaces**. You are **not allowed** to **modify the existing interfaces and classes** except the **CosmeticsFactory** class.
63+
64+
65+
![logo](https://raw.githubusercontent.com/TelerikAcademy/Common/master/logos/telerik-header-logo.png)
66+
67+
## Step by step guide
68+
69+
#### **Hint**: You don't need to take care at the Engine class and the Main method but of course you could try to understand how they work.
70+
71+
#### **Hint**: Use the least possible access modifiers for all the members.
72+
73+
**1.** You are given a skeleton of the Cosmetics shop. Please take a look at it carefully before you try to do anything. Try to understand all the classes and interfaces and how the engine works. (You should not touch the engine at all).
74+
75+
**2.** Just build the project and look at the errors.
76+
77+
![initial-errors](./imgs/initial_errors.png)
78+
79+
**3.** The errors are in CosmeticFactory class. The four methods there are not implemented.
80+
- Think what they return and what you should do.
81+
- **Hint** (create class Category which implements an interface. Think which is the interface.)
82+
83+
```cs
84+
public ICategory CreateCategory(string name)
85+
{
86+
return new Category(name);
87+
}
88+
```
89+
90+
**4.** The category class should have a constructor with name as parameter.
91+
92+
- **Hint**:
93+
94+
![category](./imgs/category-class.png)
95+
96+
- Implement the rest of the Category class by yourself.
97+
98+
**5.** Let's get back to the CosmeticFactory class
99+
100+
![interfaces](./imgs/category-class-interfaces.png)
101+
102+
- Do you see something strange here?
103+
- Lets change the return types from classes to interfaces!
104+
- Don't forget to change the return type in ICosmeticsFactory with interfaces as well.
105+
106+
**6.** ShoppingCart class
107+
- Extract interface IShoppingCart from ShoppingCart class.
108+
- Initialize the products list in the constructor and implement the methods.
109+
- **Hint**: return new collection instead of the original one.
110+
111+
![list](./imgs/list-getter.png)
112+
113+
**7.** Now you have the ShoppingCart class ready.
114+
- Look at the **Hint** at point 3 and return the ShoppingCart
115+
116+
**8.** Now you should have only two build errors.
117+
118+
![errors](./imgs/errors-2.png)
119+
120+
**9.** Lets take a look at the Shampoo class.
121+
- Do you see that the Shampoo implements IProduct and IShampoo, therefore the Shampoo is a product. Do we have another product to create?
122+
- Do you think you could abstract the product. If yes, how?
123+
- **Hint**: You could create class Product which implements IProduct interface. Think about the class modifier.
124+
Which are the different properties of the Toothpaste and the Shampoo.
125+
- **Hint**: Look at the CosmeticsFactory class and look at the signature of the methods for creating Shampoo and Toothpaste.
126+
- Do not forget to validate all the properties you need.
127+
128+
![validate](./imgs/validator.png)
129+
130+
- Remember that the price of the two products is formed differently. Think about virtual properties.
131+
132+
**10.** After you abstract the Product class and extract common properties from Shampoo and Toothpaste it is time to create the Toothpaste class. Just take a look at the Shampoo class and it is almost the same. Do not forget about the validations all the time.
133+
134+
**11.** Now you have the two classes ready and lets go back to the CosmeticsFactory class and finish the methods.
135+
- In the CreateToothpaste method you receive IList<string> and in the constructor you receive just a string. Think about conversion from List to string and be careful about the separator. You should validate every ingredient. Think about how to do it.
136+
137+
**12.** Now the build should be successful if everything is fine.
138+
139+
**13.** Lets try to put the zero test in use :)
140+
- Copy the output and put it in [https://www.diffchecker.com](https://www.diffchecker.com)
141+
![diff1](./imgs/diff-checker-1.png)
142+
143+
- If there is no validation of the property and the output is not the same on lines 3a nd 4 and you are not aware how to do it take a look at the **Hint** in point 4.
144+
- The validation for line 5 is done in the Engine.
145+
146+
**14.** If we carefully look at the input we will see that the method which is not implemented is the Print method in the Category.
147+
148+
- **Hint**:
149+
150+
![category-print](./imgs/category-print.png)
151+
- Just finish the method. You should implement the Print method of the products as well. Please note that the print mehtod of the Product could be reused in the concrete product (Shampoo or Toothpaste). Virtual methods maybe?
152+
153+
- The concrete Print mehtod could call the base Print mehtod.
154+
155+
![product-print](./imgs/product-print.png)
156+
157+
**15.** Another diff checker and the result is:
158+
![diff-2](./imgs/diff-checker-2.png)
159+
160+
- What is the problem here?
161+
- What about the price of the two products again?
162+
163+
**16.** If everything seems ok you can try it [HERE](http://bgcoder.com/Contests/Practice/Index/226#0)
164+
- Submit a **zip** file of the solution without the **bin** and **obj** folders.
165+
- What we dream to see is this :)
166+
167+
![points](./imgs/points-yeah.png)
168+
169+
170+
**16.** As you saw we don't need to look at the Engine class and the Main method at all.
171+
172+
**17.** We have used Interfaces in all the places and now we could easily add another product or even a new Command in the Engine class without making multiple if else or switch statements.
173+
174+
### **After you receive 100/100 points from BGCoder please look at your solution for the best practices in OOP. Don't forget that the bigger part of your result is hand evaluated.
Loading
39.7 KB
Loading
9.71 KB
Loading
97.8 KB
Loading
89.3 KB
Loading
12.2 KB
Loading
17.7 KB
Loading
7.09 KB
Loading
1.79 KB
Loading
6.51 KB
Loading
3.54 KB
Loading

0 commit comments

Comments
 (0)