I just tried to extend an EnumType and discovered that it is only possible when the super type is marked as abstract.
In my given case I would've liked to only extend my EnumType with attributes where needed and keep the super type usable with seperated contents where I don't need the additional attributes.
I probably learned sometime ago why this is, but can't remeber or find the information at the moment.
The idea is that any non-abstract enum knows all its values. Values of your extension would be unknown to the extended enum.
Related
The Interfaces rule in the official Go Code Review Comments document says that packages should return concrete types rather than interfaces. The motivation for this is so that:
...new methods can be added to implementations without requiring extensive refactoring.
which I accept could be a good thing.
But what if a type I'm writing has a dependency without which it cannot serve its purpose? If I export the concrete type, developers will be able to instantiate instances without that dependency. To code defensively for the missing dependency, I then have to check for it in every method implementation and return errors if it is absent. If the developer missed any hints not to do this in my documentation, she or he won't learn about the problem until run time.
On the other hand, if I declare and return an interface with the methods the client needs, I can unexport the concrete type and enforce the use of a factory method which accepts the dependency as an argument and returns the interface plus an error. This seems like a better way to ensure correct use of the package.
Am I somehow not properly getting into the go spirit by thinking like this? Is the ethic of the language that it's okay to have a less-than-perfect encapsulation to give more flexibility to developers?
You may expect developers to read the doc you provide, and you may rely on them following the rules you set. Yes, lazy developers will bump their head from time to time, but the process of developing isn't without having to learn. Everything cannot be made explicit or enforced, and that's all right.
If you have an exported struct type Example and you provide a constructor function NewExample(), that's a clear indication that NewExample() should be used to construct values of Example. Anyone attempting to construct Example manually is expected to know what fields must be set for it to be "operational". The aim is always to make the zero value fully functional, but if that can't be achieved, the constructor function is the idiomatic way to go.
This isn't uncommon, there are countless examples in the standard library, e.g. http.Request, json.Encoder, json.Decoder, io.SectionReader, template.Template.
What you must ensure is that if your package returns values of your structs, they must (should) be properly initialized. And also if others are expected to pass values of your structs created by them, you must provide an easy way for them to create valid values of your structs (constructor function). Whether the custom struct values other developers create themselves are "valid", that shouldn't be of your concern.
I have an element Enum which derrivates from an abstract Element Type.
This Type extends the Metaclass DataType and this is a necessity for me.
Is it now possible to extend the Enum, but not from this DataType?
I can only add another Metaclass and extend the Enum from it. But then after exporting the profile diagram, I have two different Elements: one based on DataType and one based on Enumeration.
I only want the last one!
Can you help me solve this? Thank you!
Have them generalize a common stereotype.
In this example, Enum will Inherit the Standard TaggedValue without getting the DataType metaclass. Type will also get the Standard TaggedValue
Please note that Common would not be usable has a stereotype as it does not extend a metaclass
I've been using mogenerator for a while now, and while there is a reasonable Getting Started Guide and a Stack Exchange article on the command line options, I haven't found a good guide for all of the functionality it provides.
In short: what, above and beyond the classes that Core Data provides for you, what does mogenerator actually generate?
(Frankly, I kept finding little pleasant surprises in the headers/implementations that I didn't realize were in there and I decided to step through the mogenerator templates and code and document what I found in a Stack Exchange Q&A. I'd love to see additional answers and edits, however. )
In addition to its core feature of a two class system, mogenerator helps you by automatically implementing a number of best practices regarding Core Data in your machine header and implementation files.
Property Accessors
Methods to access the attributes of your Entities are the core of what mogenerator generates. But there are some nice features implemented in the accessors above and beyond what the out of the box Xcode class generator provides to you.
Scalar Accessors
Xcode's built in generator gives you the option of "use scalar properties for primitive data types". This option gives you choice of having Xcode create properties with NSTimeIntervals instead of NSDates for date types, BOOLs instead of NSNumbers for boolean types, and int16_t (or similar) rather than NSNumbers.
I find this infuriating because most of the time I prefer the primitive types, but not for NSDates which are much more useful than a NSTimeInterval. So Core Data is giving me the choice of objects, in which case I will be constantly unboxing stuff and making stupid mistakes like if(myBooleanAttribute) (which is always YES because myBooleanAttribute is a NSNumber, not a BOOL). Or I can have scalars, but in that case, I get NSTimeIntervals that I'll always have to convert to NSDates. Or I can hand edit all of the generated files by hand to give me my desired mix of NSDates and BOOLs.
On the other hand, mogenerator provides you with both options. For example, you will get both a myBooleanAttribute getter that gives you an NSNumber (for easy storage in an NSArray) and a myBooleanAttributeValue getter that gives you an actual BOOL. Same with integers and floats. (Mogenerator does not generate NSTimeInterval accessors: only NSDates.)
Typed Transformable Properties
If you have a transformable property, you can set a specific UserInfo key ( attributeValueClassName ) in the attribute that will specify the class that your property will return/accept. (And it will properly forward declare the class etc.) The only place I found this documented was on Verious.
In contrast, the Xcode code generator will only type these transformable attributes as id types.
Validation Declaration
While mogenerator does not automatically generate any validation methods, it does include the proper signature as a comment in the machine h file. The seems to largely be for historical reasons, but it does mean that it is easy to copy and paste the signature if you decide to implement it in your human file implementation. (I wouldn't actually uncomment the declaration as you aren't supposed to call validation directly.)
Primitive Accessors
Core Data already provides you these accessors to the primitive values, but for some reason doesn't include them in its Xcode generated headers. Having mogenerator include them in its header files makes it much easier to access a primitive value.
Fetched Properties
mogenerator will generate accessors for fetched properties. As far as I can tell there is no way to have the Xcode generator do this.
Helper methods
Automatic NSFetchedResultsController generation
If you have a to many relationship in your Entity and you pass --template-var frc=true into mogenerator, mogenerator will automatically generate a method to create a fetch request for the child objects associated with a parent object. It even automatically generates a unique cache name, and isolates everything inside an #if TARGET_OS_IPHONE preprocessor macro.
Even if this doesn't fit your particular needs, it is a great example of how the templates can be extended.
+fetchMyFetchRequest:moc_
If you like defining your fetch requests in the model, this is a lot better way to retrieve them than hardcoded strings.
-MyEntitySet
Mogenerator uses the magic of KVC to give you a NSMutableSet proxy into your relationships.
+entityName
Need to provide a entity name to a NSFetchRequest or other Core Data method? It's easy to avoid hard coded strings by using this simple method that returns the name of the entity as an NSString.
+insertInManagedObjectContext: and entityInManagedObjectContext:
Another way to avoid hardcoding entity names is to use these helper methods.
Typed object ids
Each of your headers and implementations also includes a MyEntityID class. They are empty interfaces and implementations that merely subclass the NSManagedObjectID class. Also, each model class has a helper method called objectID that overrides the standard objectID method in NSManagedObject. The helper method does nothing but cast the superclass's return value to the MyEntityID type.
The net result: the compiler can catch your mistakes if you ever accidentally interchange your object ids from different entities.
Miscellaneous
Subclassing a Custom Superclass
One of the command line options is --base-class: which allows you to specify a base class that all of your generated classes will inherit from. This is very useful, either so that you can have a base class where you define convenience methods (which, given Core Data, you probably should) or so you can use an off the shelf Core Data toolkit like SSDataKit (or both).
includem
A simple little thing, but if you specify a --includem argument, mogenerator will generate a header file that includes all of your model header files. Convenient if you want to include all of your headers in a PCH, or something some other standard header you include.
Const Definitions of All Attributes, Relationships, Fetched Properties
An extern declaration of a struct is included in the header that has an NSString defined for every attribute and relationship defined in your Entity. This allows you to define predicates and other parameters, without baking the names of your entities into your strings. For example,
req.predicate = [NSPredicate predicateWithFormat:
#"(%K == YES) AND (%K <= %#)",MyObject.favorite, MyObject.availableDate, [NSDate date]];
(This type of struct used for "namespaced" constants is described My Mike Ash on his blog
const Definitions of User Info Keys/Values
Similarly an extern declaration of a struct is defined in the header that includes the keys as members of the struct, and the values as a values. i.e.
NSLog(#"User info for key my key is %#",MyObjectInfo.mykey) //will log "myvalue"
Alternate Templates
One of the interesting things about mogenerator is that in building mogenerator its author (Wolf Rentzsch) has basically built a generic parser and templating engine for the xcdatamodel files produced by Xcode. So you don't need to use the mogenerator templates. You can provide your own with a simple command line argument. There are lots of user contributed templates on the GitHub site.
In fact, you don't even have to use Core Data. Many of the contributed templates allow you to generate a series of ordinary NSObject model classes based on the data model. (So called PONSOs: "plain old nsobjects"). Want to use the data modeler in Xcode, but some other persistence mechanism? mogenerator can help you there.
You don't even need to generate objects at all: another interesting submitted template just provides a diff of two different model versions.
What is the best way to document the type of parameters that a function expects to receive?
Sometimes a function uses only one or two fields of an object. Sometimes this fields have common names (get(), set(), reset(), etc.). In this situation we must leave a comments:
...
#staticmethod
def get( postId, obj ):
"""obj is instance of class Type1, not Type2"""
inner = obj.get()
Is there a more explicit way to make it obvious? Maybe an object name should contain expecting typename?
Given python's 'duck-typing' (late bound) behaviour, it would be a mistake to require a particular type.
If you know which types your function must not take, you can raise an exception after detecting those; otherwise, simply raise an exception if the object passed does not support the appropriate protocol.
As to documentation, just put the required protocol in the docstring.
One strength of python is "duck typing", that is not to rely on the actual type of a variable, but on its behaviour. So I'd suggest, that you document the field, that the object should contain.
"""obj should have a field 'foo' like in class 'bar' or 'baz' """
First of all, name your methods properly, and use properties if they make sense.
You should try to get the hang of duck-typing. It's pretty useful. And if not, try and see if abstract base classes helps you do what you want.
I want to create a base object that has only methods. The object would be QUEUABLE_OBJECT_TYPE and it will have an ENQUEUE method(s). The Payload of these messages (properties) would be added by subtyping this object.
I get an error that makes it sound like you cannot:
PLS-00589: no attributes found in object type "QUEUABLE_OBJECT_TYPE"
Does anyone know a way around this error? Or is it possible in the subtypes to hide this property of the supertype?
Either would be an acceptable answer.
Everything I've read suggests it is not possible to create a type without any attributes. Nor is it possible to hide a dummy attribute in a subtype. You may simply have to have an attribute in the master type, and utilise it - e.g. by making it identify the version of the type.
Oracle does provide some generic types, see documentation for details