과제를 하다보면 클래스를 다 나눠주셔서 편하게 부분작성만 하면 편하지만 나중에 이걸 내가 어떻게 설계하지? 라는 생각이 먼저든다. 나는 10년지나도 못할듯. 그래도 조금 객체지향설계에 가까워진 느낌이 듦
알고리즘 1문제, 과제 4번 끝
void addRecipe과 PotionRecipe* addRecipe는 뭐가다른지 궁금해졌다.
일단 void를 사용하게 된 것은 클래스 내의 recipes 라는 동적배열에 저장, 관리 하고있었기 때문에 사용한 것이다.
클래스 밖의 다른 클래스에서 addRecipe를 했을때마다 값을 변하게 해주려면 addRecipe를 실행할때마다 addRecipe가 있는 RecipeManger의 전체를 훑어서 가져오는 것보단
PotionRecipe* addRecipe로 관리하면 데이터 복사값도 효율적으로 가져올 수 있음
또, 만약 값을 추가하는데 실패하거나, 값을 찾는데 실패했으면 nullptr을 반환한다
즉 성공/실패 여부를 반환값 하나로 판단할 수 있는 점도 있다.
"클래스를 건드렸을때 다른 클래스가 영향을 받지 않아야 한다"(캡슐화)
클래스를 건드렸을때 다른 클래스가 수정이 된다면 오류를 잡을때 시간이 오래 걸리기 때문에 이렇게 설계해야한다고 들었다 그런데 이렇게 되면 addRecipe를 수정할때마다 StockManager클래스가 수정될 수 있기 때문에 잘못된게 아닌가? 생각했다
하지만 const(읽기만 가능하고 수정은 못함)를 붙여서 쓴다면 StockManager에서 레시피 정보를 볼 수는있지만 수정할 수는 없음.
결합도는 낮추고(Loose Coupling), 캡슐화(Enacapsulation)는 유지하여 성능과 안정성을 챙김.
예제에 다른 것들은 PotionRecipe*로 넘겨주었지만 vector<PotionRecipe*> 벡터는 그러지않는 모습을 발견했다.
Dangling Pointer때문에 안정성을 챙기기 위해
RecipeManager에 레시피 10개에 재료가 100개가 있고,
그 주소들을vector<PotionRecipe*>에 담아서StockManager에게 줬다고 하자.
그 직후에RecipeManager에서 레시피를 삭제하거나,vector가 메모리 이사를 가버린다면?
StockManager가 들고 있는 주소들은 가짜 주소가 된다.
nullptr인지 체크하기 힘들어서
하나를 포인터 주소로 주면nullptr인지 아닌지 체크하면 끝이지만**vector안에 든 포인터가 유효한지 일일이 체크하는건 너무 힘듦**
그래서 안전한 복사본vector<PoitonRecipe>를 만들어서 주는 쪽을 선택하기도 함
-여러 객체를 컨테이너(vector)에 담아 반환할 때는 메모리 안정성과 관리의 편의성을 위해 복사(Value) 방식을 선택하기도 함
- 그냥 = 을 쓰는 값들은 자료형을 맞춰라
처음에는 main을 좀 적게쓰더라도 class를 좀 더럽게 쓰자라는 생각이였다.
하지만 객체지향설계라는 것은 유지보수를 할때 편하고 읽기 쉽게 하는 것 이란걸 잊어먹고있었다.
class에는 return값만 제대로 작성해도 main에서 인터페이스를 구현하는게 더 재사용성이 높고 깔끔하다는 것을 알았다.
클래스 안에 cout이 있으면 코드를 다 뜯어고쳐야 하지만, 값만 리턴하면 엔진 UI같은 곳에 그대로 띄울 수 있다.