trong một thời gian khá tôi đã làm việc trên một ứng dụng. Khi lập trình chỉ là một sở thích, dự án này đã mất quá nhiều thời gian, nhưng đó là ngoài điểm. Bây giờ tôi đang ở một điểm mà mọi "vấn đề" trở nên khó giải quyết một cách khủng khiếp. Và tôi đang nghĩ đến việc tái cấu trúc mã, tuy nhiên điều đó sẽ dẫn đến việc viết lại "hoàn chỉnh".Mô hình lập trình; tự hỏi nếu viết lại/refactoring là cần thiết
Hãy để tôi giải thích sự cố và cách tôi giải quyết sự cố hiện tại. Về cơ bản tôi có dữ liệu và tôi để mọi thứ xảy ra trên dữ liệu này (tôi đã mô tả về mọi chương trình không phải là tôi?). Chuyện gì xảy ra là:
dữ liệu -> hỏi xem để hiển thị -> hiển thị xem dữ liệu dựa trên dữ liệu thực tế xem trả về đầu vào sử dụng -> Xóa dữ liệu -> yêu cầu "người thi hành" để thực hiện nó -> Xóa dữ liệu mới
Bây giờ điều này đã từng làm việc rất tốt, và tôi đã suy nghĩ ban đầu "hey tôi có thể ví dụ như thay đổi dấu nhắc lệnh bằng cách qt, hoặc cửa sổ - hoặc thậm chí mất rằng bên ngoài (C#) và chỉ cần gọi chương trình này" .
Tuy nhiên, khi chương trình phát triển, nó ngày càng trở nên mệt mỏi hơn. Vì điều quan trọng nhất là dữ liệu được hiển thị theo các cách khác nhau tùy thuộc vào dữ liệu và quan trọng hơn - nơi dữ liệu được định vị. Vì vậy, tôi đã trở lại cây & thêm vào một cách nào đó để "theo dõi" những gì các dòng phụ huynh là ". Sau đó, người xem chung sẽ tìm kiếm các widget thực tế cụ thể nhất.
Sự cố bắt đầu khi cập nhật cho "dữ liệu" mới - Tôi phải xem xét tất cả nội dung - trình xem, tiết kiệm, v.v ... Cập nhật cơ chế kiểm tra đã cho tôi nhiều lỗi .. Mọi thứ giống như "hey tại sao nó lại hiển thị tiện ích sai?"
Bây giờ tôi hoàn toàn có thể hoán đổi nó và thay vào đó là cơ sở hạ tầng cây gọi cho người xem chung, tôi sẽ sử dụng khả năng của cây OO "nội bộ". các nút sẽ là childs (& whe n một người xem mới hoặc cơ chế lưu là cần thiết một đứa trẻ mới được hình thành).
Điều này sẽ loại bỏ cơ chế kiểm tra khó khăn, nơi tôi kiểm tra vị trí trong cây. Tuy nhiên, nó có thể mở ra một toàn bộ các giun khác. Và tôi muốn nhận xét về điều này? Tôi có nên giữ người xem hoàn toàn riêng biệt - gặp khó khăn khi kiểm tra dữ liệu không? Hoặc là cách tiếp cận mới tốt hơn, nhưng nó kết hợp dữ liệu thực hiện & thành một nút duy nhất. (Vì vậy, nếu tôi muốn thay đổi từ qt nói cli/C# nó trở nên gần như bất khả thi)
phương pháp Những gì tôi nên theo đuổi cuối cùng? Ngoài ra có cái gì khác tôi có thể làm gì? Để giữ người xem tách biệt, nhưng vẫn không phải kiểm tra để xem tiện ích nào sẽ được hiển thị?
CHỈNH SỬA, chỉ để hiển thị một số "mã" và cách chương trình của tôi hoạt động. Không chắc chắn nếu điều này là tốt như tôi đã nói nó đã trở thành khá một clusterfuck của phương pháp luận.
Nó có nghĩa là hợp nhất một số "dự án gamemaker" với nhau (như GM: studio kỳ lạ thiếu tính năng đó). Các tệp dự án Gamemaker chỉ đơn giản là tập hợp các tệp xml. (Tệp xml chính chỉ có liên kết đến các tệp xml khác và tệp xml cho từng tài nguyên -object, sprite, sound, room etc-).Tuy nhiên có một số 'quirks' mà làm cho nó không thực sự có thể đọc với một cái gì đó như cây tăng tài sản hoặc qt: 1) thứ tự của các thuộc tính/nút con là rất quan trọng tại một số phần của các tập tin. và 2) không gian trắng thường bị bỏ qua tuy nhiên tại các điểm khác, điều rất quan trọng là phải bảo tồn nó.
Điều đó đang được nói cũng có rất nhiều điểm mà nút chính xác giống nhau .. Giống như cách nền có thể có <width>200</width>
và một phòng cũng có thể có. Tuy nhiên, đối với người dùng nó là khá quan trọng mà chiều rộng ông đang nói về.
Anyways, do đó, "nói chung xem" (AskGUIFn) có typedefs sau đây để xử lý này:
typedef int (AskGUIFn::*MemberFn)(const GMProject::pTree& tOut, const GMProject::pTree& tIn, int) const;
typedef std::vector<std::pair<boost::regex, MemberFn> > DisplaySubMap_Ty;
typedef std::map<RESOURCE_TYPES, std::pair<DisplaySubMap_Ty, MemberFn> > DisplayMap_Ty;
đâu "GMProject :: pTree" là một nút cây, RESOURCE_TYPES là một hằng số để theo dõi trong loại tài nguyên nào tôi đang ở thời điểm này (sprite, object etc). Các "memberFn" sẽ ở đây chỉ đơn giản là một cái gì đó mà tải một widget. (Mặc dù AskGUIFn không phải là trình xem tổng quát duy nhất tất nhiên, trình xem này chỉ được mở nếu các trình xử lý ghi đè, bỏ qua, đổi tên khác "tự động" không thành công).
Bây giờ để hiển thị như thế nào các bản đồ này được khởi tạo (tất cả mọi thứ trong không gian tên "MW" là một widget qt):
AskGUIFn::DisplayMap_Ty AskGUIFn::DisplayFunctionMap_INIT() {
DisplayMap_Ty t;
DisplaySubMap_Ty tmp;
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^instances "), &AskGUIFn::ExecuteFn<MW::RoomInstanceDialog>));
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^code $"), &AskGUIFn::ExecuteFn<MW::RoomStringDialog>));
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^(isometric|persistent|showcolour|enableViews|clearViewBackground) $"), &AskGUIFn::ExecuteFn<MW::ResourceBoolDialog>));
//etc etc etc
t[RT_ROOM] = std::pair<DisplaySubMap_Ty, MemberFn> (tmp, &AskGUIFn::ExecuteFn<MW::RoomStdDialog>);
tmp.clear();
//repeat above
t[RT_SPRITE] = std::pair<DisplaySubMap_Ty, MemberFn>(tmp, &AskGUIFn::ExecuteFn<MW::RoomStdDialog>);
//for each resource type.
Sau đó, khi datastructure cây nói với người xem nói chung nó mong muốn được hiển thị cho người xem thực thi chức năng sau:
AskGUIFn::MemberFn AskGUIFn::FindFirstMatch() const {
auto map_loc(DisplayFunctionMap.find(res_type));
if (map_loc != DisplayFunctionMap.end()) {
std::string stack(CallStackSerialize());
for (auto iter(map_loc->second.first.begin()); iter != map_loc->second.first.end(); ++iter) {
if (boost::regex_search(stack, iter->first)) {
return iter->second;
}
}
return map_loc->second.second;
}
return BackupScreen;
}
Và đây là nơi vấn đề bắt đầu thẳng thắn. Chức năng CallStackSerialize()
phụ thuộc vào ngăn xếp cuộc gọi .. Tuy nhiên, lệnh gọi_được lưu trữ bên trong "trình xử lý". Tôi đã lưu trữ nó ở đó vì mọi thứ bắt đầu từ một trình xử lý. Tôi không thực sự chắc chắn nơi tôi nên lưu trữ này "call_stack". Giới thiệu một đối tượng khác theo dõi những gì đang xảy ra? Tôi đã thử đi tuyến đường nơi tôi lưu trữ phụ huynh với chính nút đó. (Ngăn chặn sự cần thiết cho một cuộc gọi ngăn xếp). Tuy nhiên điều đó không diễn ra tốt đẹp như tôi mong muốn: mỗi nút chỉ đơn giản có một vectơ chứa các nút con của nó. Vì vậy, bằng cách sử dụng con trỏ là ra khỏi câu hỏi để trỏ đến lưu ý cha mẹ ... (PS: có lẽ tôi nên cải cách này trong một câu hỏi khác ..)
+1, cho các số liệu. Nếu không đọc câu hỏi, nó đơn giản trông rất tuyệt. – iammilind
Bạn có quen thuộc với "[Hiệu ứng nền tảng bên trong] (http://en.wikipedia.org/wiki/Inner_platform_effect)" không? Tôi không hiểu vấn đề của bạn đủ tốt để rút ra bất kỳ kết luận nào (và tôi chắc chắn không biết gì về ứng dụng của bạn!) Nhưng nếu bạn không quen thuộc với thuật ngữ thì nó đáng để nghiên cứu một chút. Đấu tranh để sửa đổi một hệ thống rất phức tạp nhằm mục đích là một khuôn khổ siêu mục đích nói chung giống như một triệu chứng của antipattern này ... – Rook
không phải là các nút dữ liệu của bạn cần một loại hồ sơ khi chúng được tạo ra, hồ sơ mô tả cách thức để trình bày, hành động và cứu họ? – armel