Sum types on Dart - oop

What's an idiomatic way to represent sum types in OOP, more specifically in Dart language?
I'm building a questionnaire app on Flutter.
Say I have a sum type data structure in a functional language like this:
data AnswerSpec = Boolean
| ChooseOne [Text]
| ChooseOneWithOpen [Text]
| ChooseMany [Text]
| ChooseManyWithOpen [Text]
| Open
| Duration
| SleepDuration
| Datetime -- date + time
| Count
This defines the question's accepted answer type/choice. Each question has only one of those associated with it.
Ideally, I'd also like to associate the given answer with the same entity, because I need to validate (build validation methods) that the given answer adheres to the accepted answer choice.
Example
Question: Which part of your body did you exercise today?
Accepted Answer type: ChooseMany ["Upper body", "Lower body"] (the user can choose both)
User's answer: ["Upper body"]
As you can see, the answer itself may be of type int, string, List<string>, DateTime or even a combination of those, such as List<string> + string.
Can you help me understand what's the best way to model this on Dart, with its inheritance abstractions like class, abstract class and mixin?

Related

Spock Extension - Extracting variable names from Data Tables

In order to extract data table values to use in a reporting extension for Spock, I am using the
following code:
#Override
public void beforeIteration(IterationInfo iteration) {
Object[] values = iteration.getDataValues();
}
This returns to me the reference to the objects in the data table. However, I would like to get
the name of the variable that references the value.
For example, in the following test:
private static User userAge15 = instantiateUserByAge(15);
private static User userAge18 = instantiateUserByAge(18);
private static User userAge19 = instantiateUserByAge(19);
private static User userAge40 = instantiateUserByAge(40);
def "Should show popup if user is 18 or under"(User user, Boolean shouldShowPopup) {
given: "the user <user>"
when: "the user do whatever"
...something here...
then: "the popup is shown is <showPopup>"
showPopup == shouldShowPopup
where:
user | shouldShowPopup
userAge15 | true
userAge18 | true
userAge19 | false
userAge40 | false
}
Is there a way to receive the string “userAge15”, “userAge18”, “userAge19”, “userAge40” instead of their values?
The motivation for this is that the object User is complex with lots of information as name, surname, etc, and its toString() method would make the where clause unreadable in the report I generate.
You can use specificationContext.currentFeature.dataVariables. It returns a list of strings containing the data variable names. This should work both in Spock 1.3 and 2.0.
Edit: Oh sorry, you do not want the data variable names ["a", "b", "expected"] but ["test1", "test1", "test2"]. Sorry, I cannot help you with that and would not if I could because that is just a horrible way to program IMO. I would rather make sure the toString() output gets shortened or trimmed in an appropriate manner, if necessary, or to (additionally or instead) print the class name and/or object ID.
Last but not least, writing tests is a design tool uncovering potential problems in your application. You might want to ask yourself why toString() results are not suited to print in a report and refactor those methods. Maybe your toString() methods use line breaks and should be simplified to print a one-line representation of the object. Maybe you want to factor out the multi-line representation into other methods and/or have a set of related methods like toString(), toShortString(), toLongString() (all seen in APIs before) or maybe something specific like toMultiLineString().
Update after OP significantly changed the question:
If the user of your extension feels that the report is not clear enough, she could add a column userType to the data table, containing values like "15 years old".
Or maybe simpler, just add an age column with values like 15, 18, 19, 40 and instantiate users directly via instantiateUserByAge(age) in the user column or in the test's given section instead of creating lots of static variables. The age value would be reported by your extension. In combination with an unrolled feature method name using #age this should be clear enough.
Is creating users so super expensive you have to put them into static variables? You want to avoid statics if not really necessary because they tend to bleed over side effects to other tests if those objects are mutable and their internal state changes in one test, e.g. because someone conveniently uses userAge15 in order to test setAge(int). Try to avoid premature optimisations via static variables which often just save microseconds. Even if you do decide to pre-create a set of users and re-use them in all tests, you could put them into a map with the age being the key and conveniently retrieve them from your feature methods, again just using the age in the data table as an input value for querying the map, either directly or via a helper method.
Bottom line: I think you do not have to change your extension in order to cater to users writing bad tests. Those users ought to learn how to write better tests. As a side effect, the reports will also look more comprehensive. 😀

Are extensible records useless in Elm 0.19?

Extensible records were one of the most amazing Elm's features, but since v0.16 adding and removing fields is no longer available. And this puts me in an awkward position.
Consider an example. I want to give a name to a random thing t, and extensible records provide me a perfect tool for this:
type alias Named t = { t | name: String }
„Okay,“ says the complier. Now I need a constructor, i.e. a function that equips a thing with specified name:
equip : String -> t -> Named t
equip name thing = { thing | name = name } -- Oops! Type mismatch
Compilation fails, because { thing | name = ... } syntax assumes thing to be a record with name field, but type system can't assure this. In fact, with Named t I've tried to express something opposite: t should be a record type without its own name field, and the function adds this field to a record. Anyway, field addition is necessary to implement equip function.
So, it seems impossible to write equip in polymorphic manner, but it's probably not a such big deal. After all, any time I'm going to give a name to some concrete thing I can do this by hands. Much worse, inverse function extract : Named t -> t (which erases name of a named thing) requires field removal mechanism, and thus is not implementable too:
extract : Named t -> t
extract thing = thing -- Error: No implicit upcast
It would be extremely important function, because I have tons of routines those accept old-fashioned unnamed things, and I need a way to use them for named things. Of course, massive refactoring of those functions is ineligible solution.
At last, after this long introduction, let me state my questions:
Does modern Elm provides some substitute for old deprecated field addition/removal syntax?
If not, is there some built-in function like equip and extract above? For every custom extensible record type I would like to have a polymorphic analyzer (a function that extracts its base part) and a polymorphic constructor (a function that combines base part with additive and produces the record).
Negative answers for both (1) and (2) would force me to implement Named t in a more traditional way:
type Named t = Named String t
In this case, I can't catch the purpose of extensible records. Is there a positive use case, a scenario in which extensible records play critical role?
Type { t | name : String } means a record that has a name field. It does not extend the t type but, rather, extends the compiler’s knowledge about t itself.
So in fact the type of equip is String -> { t | name : String } -> { t | name : String }.
What is more, as you noticed, Elm no longer supports adding fields to records so even if the type system allowed what you want, you still could not do it. { thing | name = name } syntax only supports updating the records of type { t | name : String }.
Similarly, there is no support for deleting fields from record.
If you really need to have types from which you can add or remove fields you can use Dict. The other options are either writing the transformers manually, or creating and using a code generator (this was recommended solution for JSON decoding boilerplate for a while).
And regarding the extensible records, Elm does not really support the “extensible” part much any more – the only remaining part is the { t | name : u } -> u projection so perhaps it should be called just scoped records. Elm docs itself acknowledge the extensibility is not very useful at the moment.
You could just wrap the t type with name but it wouldn't make a big difference compared to approach with custom type:
type alias Named t = { val: t, name: String }
equip : String -> t -> Named t
equip name thing = { val = thing, name = name }
extract : Named t -> t
extract thing = thing.val
Is there a positive use case, a scenario in which extensible records play critical role?
Yes, they are useful when your application Model grows too large and you face the question of how to scale out your application. Extensible records let you slice up the model in arbitrary ways, without committing to particular slices long term. If you sliced it up by splitting it into several smaller nested records, you would be committed to that particular arrangement - which might tend to lead to nested TEA and the 'out message' pattern; usually a bad design choice.
Instead, use extensible records to describe slices of the model, and group functions that operate over particular slices into their own modules. If you later need to work accross different areas of the model, you can create a new extensible record for that.
Its described by Richard Feldman in his Scaling Elm Apps talk:
https://www.youtube.com/watch?v=DoA4Txr4GUs&ab_channel=ElmEurope
I agree that extensible records can seem a bit useless in Elm, but it is a very good thing they are there to solve the scaling issue in the best way.

how to list out a certain type definition in elm

type alias Employee =
{ role : Role, name : String }
type Role
= Engineer
| Manager
| Sales
| Accounting
| Hr
generateSample =
Role.all |> List.map createModelWithType
I need to accomplish Role.all, which even Role in this case is inaccessible. What's the best way to accomplish / alternative way to express this.
There is no automatic way to list all constructors of a type. You could build a list like this:
allRoles : List Role
allRoles =
[ Engineer
, Manager
, Sales
, Accounting
, Hr
]
In Elm, there is no concept of a simple enumeration similar to other languages. Type constructors could also have arguments, which may help in understanding why there is no built-in way to enumerate a list of constructors.
There are many considerations when choosing a type. It depends on what behavior will be used with the data. Maybe as you are learning you could simply choose a data type that works and seems simple enough to work with. With experience you will see the advantages of choosing a type over the other.
To get more inspired in the way of thinking in choosing type for different problems you might want to take a look at this presentation: https://www.youtube.com/watch?v=XpDsk374LDE
There are two topics mixed in the presentation and one of them is how choosing type for different behaviors.
Here is one way to do it:
type Alias Role =
{ Engineer : Bool
, Manager : Bool
, Sales : Bool
, Accounting : Bool
, Hr : Bool
}

Aggregation in class diagram and class properties

In a lecture about Class diagrams the following slide appeared which describes the relationship in an Elevator system:
The lecture called the black headed arrows a "composite aggregation" relationship which means that the child cannot exist independently of the parent.
In this elevator system example, the Motor object is irrelevant outside of the Elevator object.
What I don't understand though is how the composite aggregation appears in the code itself. I'd expect there to be a "myMotor" property in the Elevator but there isn't.
Is it because by drawing this relationship we tell the programmer that he needs to implement it but the implementation details are his to choose?
As opposed to the father object's proprties which are stated explicitly (like the elevator's isActive boolean property)?
U.M.L. can be used, in several ways,as very conceptual design tool, or a more specific programming design tool.
So, when representing a composite aggregation, it can be represented in several ways.
Sometimes, you may want to display all members of a class. Bad, when there are too much members.
+--------------------------+
| ElevatorClass |
+--------------------------+
| [+] boolean: isActive |
| [+] boolean: isInOrder |
| [+] Floor: Location |
| [+] MotorClass: Motor |
| [+] DoorClass: Door |
+--------------------------+
| [+] startOperation() |
| [+] stopOperation() |
| [+] gooUp() |
| [+] gooDown() |
| [+] openDoor() |
| [+] closeDoor() |
+--------------------------+
Sometimes, you may want to hide all members of a class. Good, when you want to focus in the class, not the members. Note: This may be the case you are looking right now.
+--------------------------+1 1+--------------------------+
| ElevatorClass |------<*>| RescueButtonClass |
+--------------------------+ +--------------------------+
Sometimes, you may want to show some members of a class, and hide another.
+--------------------------+ 1 1 +--------------------------+
| ElevatorClass |------<*>| MotorButtonClass |
+--------------------------+ +--------------------------+
| [+] boolean: isActive |
| [+] boolean: isInOrder |
| [+] Floor: Location |
| [+] MotorClass: Motor |
| [+] DoorClass: Door |
+--------------------------+
To make things a little complicated, the motor, as well as the other elements, doesn't necesarilly have to be referenced by a reference member in the elevator class.
Example (c style):
class ElevatorClass {
public:
List<ComponentClass*> Components;
...
void AddComponent(ComponentClass* ThisComponent);
} // class ElevatorClass
...
MyElevator.AddComponent(MyMotor);
In the previous code example, the member is not referenced directly.
Personally I agree with you that this its very clear:
class ElevatorClass {
public:
MotorClass* Motor;
MotorClass* Motor;
} // class ElevatorClass
Cheers.
For a Composite Aggregation (also called Composition), USUALLY this indicates a parent-child relationship. In your example, an Elevator object in your code would contain a reference to only one Motor object. Here is a link to a blog post that may explain it better. Look for the Composition section:
http://aviadezra.blogspot.com/2009/05/uml-association-aggregation-composition.html
I think this representation makes sense for all the objects pictured except maybe StopRequest. Personally I would not have pictured that as a Composition to the Elevator object, but remember that UML is not an exact science.
Your assumption is correct - UML relations doesn't specify the implementation details. In case of composition the requirement is that Motor object lifetime is bounded to the containing Elevator object lifetime. This can be achieved in several ways (and dependens on the language you use as well). It can be a property inside the Elevator and in this case it will be automatically destroyed along with the the containing Elevator. On the other hand, it can be an external object which is instantiated and freed manually during the lifetime of the containing Elevator object. The implementation depends on the specific case and additional design considerations, such as simplicity, flexibility, modularity etc.
There are many details that can be added to the diagram. The creator of the diagram needs to consider what to include and what to omit. For example, private properties are usually related to implementation details and aren't interesting for the class diagram thus they won't be mentioned. Properties mentioned explicitly imply a composition relation between the containing object and the property. Such notion is usually used for primitive properties, such as boolean, int etc. For a more complex properties an explicit UML relation is usually used to depict the relation between the objects (like between Elevator and Motor).

What is the difference between the concept of 'class' and 'type'?

i know this question has been already asked, but i didnt get it quite right, i would like to know, which is the base one, class or the type. I have few questions, please clear those for me,
Is type the base of a programing data type?
type is hard coded into the language itself. Class is something we can define ourselves?
What is untyped languages, please give some examples
type is not something that fall in to the oop concepts, I mean it is not restricted to oop world
Please clear this for me, thanks.
I didn't work with many languages. Maybe, my questions are correct in terms of : Java, C#, Objective-C
1/ I think type is actually data type in some way people talk about it.
2/ No. Both type and class we can define it. An object of Class A has type A. For example if we define String s = "123"; then s has a type String, belong to class String. But the vice versa is not correct.
For example:
class B {}
class A extends B {}
B b = new A();
then you can say b has type B and belong to both class A and B. But b doesn't have type A.
3/ untyped language is a language that allows you to change the type of the variable, like in javascript.
var s = "123"; // type string
s = 123; // then type integer
4/ I don't know much but I think it is not restricted to oop. It can be procedural programming as well
It may well depend on the language. I treat types and classes as the same thing in OO, only making a distinction between class (the definition of a family of objects) and instance (or object), specific concrete occurrences of a class.
I come originally from a C world where there was no real difference between language-defined types like int and types that you made yourself with typedef or struct.
Likewise, in C++, there's little difference (probably none) between std::string and any class you put together yourself, other than the fact that std::string will almost certainly be bug-free by now. The same isn't always necessary in our own code :-)
I've heard people suggest that types are classes without methods but I don't believe that distinction (again because of my C/C++ background).
There is a fundamental difference in some languages between integral (in the sense of integrated rather than integer) types and class types. Classes can be extended but int and float (examples for C++) cannot.
In OOP languages, a class specifies the definition of an object. In many cases, that object can serve as a type for things like parameter matching in a function.
So, for an example, when you define a function, you specify the type of data that should be passed to the function and the type of data that is returned:
int AddOne(int value) { return value+1; } uses int types for the return value and the parameter being passed in.
In languages that have both, the concepts of type and class/object can almost become interchangeable. However, there are many languages that do not have both. For instance, I believe that standard C has no support for custom-defined objects, but it certainly does still have types. On the otherhand, both PHP and Javascript are examples of languages where type is very loosely defined (basically, types are either single item, collection/array/object, or undefined [js only]), but they have full support for classes/objects.
Another key difference: you can have methods and custom-functions associated with a class/object, but not with a standard data-type.
Hopefully that clarified some. To answer your specific questions:
In some ways, type could be considered a base concept of programming, yes.
Yes, with the exception that classes can be treated as types in functions, as in the example above.
An untyped language is one that lets you use any type of variable interchangeably. Meaning that you can handle a string with the same code that handles an int, for instance. In practice most 'untyped' languages actually implement a concept called duck-typing, so named because they say that 'if it acts like a duck, it should be treated like a duck' and attempt to use any variable as the type that makes sense for the code encountered. Again, php and javascript are two languages which do this.
Very true, type is applicable outside of the OOP world.