Предположим, что существует поток функций на C++
step1();
step2();
step3();
step4();
step5();
и они взаимодействуют, добавляя и изменяя данные в классе данных D (только данные, без функций). Например, step1()
создает d
в D
, step2()
изменяет d
, а step5()
использует d
.
Проблема такой конструкции заключается в том, что на данном шаге функции неясно, произведен ли уже какой-либо член данных в D и готов ли он к использованию. Более того, неясно, какой член данных в D производится на каком шаге.
Я хотел бы узнать, есть ли хороший способ (возможно, какой-то шаблон проектирования) сделать класс данных D более мощным, чтобы было понятно, был ли член данных в D произведен на данном шаге. Спасибо.
DataStruct d;
step1(d);
step2(d);
step3(d);
step4(d);
step5(d);
С точки зрения понимания того, какой этап вносит вклад в какое поле (я) структуры, в тривиальном случае может быть просто проще проверить код в каждом методе, но если есть необходимость в реальной организации и ясности, то обычно вы начинаете чтобы отразить это в схеме именования полей или в определении нескольких структур, которые представляют окончательную структуру на разных этапах производства.
Таким образом, со схемой именования у вас может быть:
struct DataStruct {
int S1Field1;
int S1Field2;
int S1Field3;
int S2Field4;
int S3Field5;
(etc.)
}
... с префиксом, обозначающим этап, на котором создается это поле.
Если по какой-либо причине этого недостаточно, вы можете начать определять отдельные структуры:
struct DataStructBuild1 {
int Field1; //new
int Field2; //new
int Field3; //new
}
struct DataStructBuild2 {
int Field1; //from Build 1
int Field2; //from Build 1
int Field3; //from Build 1
int Field4; //new
}
(etc.)
DataStructBuild1 d1;
DataStructBuild2 d2;
DataStructBuild3 d3;
step1(d1);
step2(d1, out d2);
step3(d2, out d3);
(etc.)
Ясно, что при таком последнем подходе более ранние шаги не могут ссылаться на поля, которые еще не созданы, потому что структура, которую они передают для изменения, не содержит никаких несформированных полей — она содержит только доступные входные данные и вместилища для выходных данных. данный этап.
Также может быть полезно использовать комбинацию обоих подходов — отдельные структуры для каждого состояния и префикс имени для представления этапа, на котором эти поля становятся доступными — если количество полей велико и есть желание тщательно отслеживать из которых поля уже застроены, а какие строятся.
И при необходимости вы можете определить окончательную структуру, которая содержит чистую схему именования без префиксов, которые добавляются только как леса для лучшего понимания в контексте процесса сборки, но которые не нужно сохранять в других частях. программы позже.
Я должен добавить одно последнее замечание: ответ @Christophe, связанный с ООП, был бы более подходящим, когда этап построения данных настолько велик или сложен, что он каким-то образом находился бы в компетенции нескольких групп программистов (или, по крайней мере, несколько человек, у которых есть отдельные области вызывает озабоченность), и должна быть система геттеров и сеттеров, определяющая интерфейс между сферами двух команд, исключения, чтобы гарантировать, что люди, которые не писали код и не знакомы с его внутренностями, были предупреждены, когда они не используют его должным образом, и так далее.
Когда вы не работаете на стыке между двумя командами, а работаете исключительно в рамках своей области, ООП обычно представляет собой очень сложный и тяжеловесный подход к решению проблем.