samedi 16 novembre 2019

What design pattern should I use for a questionnaire?

Let's say we have a questionnaire about health and it has different parameters with different types: gender, age, height, weight, goal, activity, pregnancy. It is possible that there will be more parameters, or some of them are disabled. We have some kind of array of views which are able to display the parameters and send event if user changes them. Views can be the same class for different parameters and not the same for others. We also have a server which can receive these parameters and send us a pre filled version.

I think a plain object or structure containing all these fields is not a good idea in this case because it creates a lot of boilerplate, and it seems to be not as robust as needed.

I think more in way of an array of enums with associated values. But for now it also creates a lot of problems. Roughly right now I have a enum like that:

public enum HealthParameterType {
    case gender(NutrientsGenderEntity?)
    case age(Int?)
    case height(Int?)
    case weight(Int?)
    case goal(NutrientsGoalEntity?)
    case activity(NutrientsActivityEntity?)
    case pregnancy(NutrientsPregnancyEntity?)
}

Every parameter View class a View Model which can transform the value to different view representations, and it looks like that:

    var value: String {
        var result: String?

        switch health {
        case .activity(let value): result = value?.rawValue
        case .age(let value), .height(let value), .weight(let value): result = value == nil ? nil : "\(value!)"
        case .gender(let value): result = value?.rawValue
        case .goal(let value): result = value?.rawValue
        case .pregnancy(let value): result = value?.rawValue
        }
        return result ?? ""
    }

    var title: String {
        switch health {
        case .age: return "Возраст"
        case .height: return "Рост (см)"
        case .weight: return "Вес (кг)"
        case .gender: return "Пол"
        case .goal: return "Цель"
        case .activity: return "Активность"
        case .pregnancy: return "Беременость"
        }
    }

And it still looks kind of bulky. I don't even know if it was a good idea after all to use Enums. Is there another way? Or is it beneficial to use the Enum strategy, just make some enhancements?

PS. also swift does not support Codable enums with associated values, so there are also some hacks used like in this SO question https://stackoverflow.com/a/44726160/3992237

Aucun commentaire:

Enregistrer un commentaire