У меня есть несколько взаимосвязанных объектов:
Например, отжимания, подтягивания, приседания. Каждое упражнение имеет название, задействованные мышцы (грудь, ноги...), шаги выполнения и тип категории.
Это перечисление, которое показывает, как измеряется это упражнение.
bodyweightReps
, как вы
необходимо измерять только выполненные повторения.weightReps
, при котором вы фиксируете как вес на штанге, так и количество выполненных повторений.bodyweightReps
нужно записать только 1 параметр repetition
,weightReps
нужно 2, 1 для weight
и 1 для repetition
).Это действие, выполняемое во время тренировки. В нем есть упражнение, некоторые примечания и список выполненных комплексов тренировок.
Это комплекс тренировок. Он имеет время отдыха и список показателей для сохраненных значений (например, количество выполненных повторений, использованный вес...).measures
набора тренировок зависит от родительской категории упражнений «Тренировка», так как набор тренировок со штангой «Приседания со штангой» требует измерения веса и количества выполненных повторений, так как категория упражнений — weightReps
.
Как видите, WorkoutActivity имеет упражнение, а структура дочернего свойства WorkoutSet Measures зависит от родительского свойства категории упражнений WorkoutActivity.
enum ExerciseType {
weightReps,
bodyWeightReps,
distance,
time
}
class Exercise {
String name;
List<String> executionSteps;
ExerciseType category;
}
class Workout {
String name
List<WorkoutActivity> activities;
}
class WorkoutActivity {
String note;
Exercise exercise;
List<WorkoutSet> sets;
}
class WorkoutSet {
int restTime;
List<double> measures;
}
Приведенная выше структура не гарантирует, что наборы тренировок тренировки, тип категории упражнений которых bodyweightReps
, имеют только одну меру, а также то, что если тип категории weightReps
имеет 2 меры.
Эта проблема поднимает некоторые связанные проблемы, которые нельзя игнорировать.
Есть ли лучший способ структурировать сущности, чтобы показатели дочернего WorkoutSet можно было заставить следовать структуре типа родительской категории упражнений Workout Activity?
Предпочтительно время компиляции, но допускается и время выполнения :)
О каком языке мы говорим? Моё обоснованное предположение - C#...
Я использую dart для Flutter, но более или менее могу расшифровать другие языки, большое спасибо!
В .NET 5 было введено несколько новых атрибутов анализа кода, например MemberNotNullWhen. Было бы полезно, если бы внутри WorkoutSet
были выделены поля для показателей weight
и repetition
.
Поскольку у нас есть набор мер и мы говорим о разных языках программирования, позвольте мне начать с простого примера.
Для простоты я переместил ExerciseType
на WorkoutSet
.
abstract class WorkoutSet
{
ExerciseType category;
int restTime;
List<double> measures;
public sealed class WeightReps : WorkoutSet
{
public WeightReps (int restSeconds, double repetition, double weight )
{
this.category = ExerciseType.weightReps;
this.restTime = restSeconds;
this.measures = new() { repetition, weight };
}
}
public sealed class BodyWeightReps : WorkoutSet
{
public BodyWeightReps (int restSeconds, double repetition )
{
this.category = ExerciseType.bodyWeightReps;
this.restTime = restSeconds;
this.measures = new() { repetition };
}
}
}
Это позволит вам создать класс WeightReps
или BodyWeightReps
. Их конструкторы получают необходимое количество параметров и знают, как инициализировать данный экземпляр. Вы не можете напрямую создать WorkoutSet
.
new WorkoutSet.BodyWeightReps((int)data.rest.TotalSeconds, data.repetition)
new WorkoutSet.WeightReps((int)data.rest.TotalSeconds, data.repetition, data.weight);
В случае C# вы можете продвинуть эту идею немного дальше с помощью неявных операторов для автоматического преобразования ValueTuple
в производный класс WorkoutSet
.
public static implicit operator WorkoutSet( (TimeSpan rest, double repetition) data )
=> new WorkoutSet.BodyWeightReps((int)data.rest.TotalSeconds, data.repetition);
public static implicit operator WorkoutSet( (TimeSpan rest, double repetition, double weight ) data )
=> new WorkoutSet.WeightReps((int)data.rest.TotalSeconds, data.repetition, data.weight);
Применение
WorkoutSet bodyWeightReps = (TimeSpan.FromMinutes(0.5), repetition: 1.0d);
WorkoutSet weightReps = (TimeSpan.FromSeconds(42), repetition: 1.0d, weight: 2.0d);
Здесь вы можете найти рабочий пример: https://dotnetfiddle.net/P4rf2P
Хотите ли вы иметь гарантии времени выполнения или компиляции?