I'm beginning development on a nontrivial application for which we're considering GraphQL. When working on the initial draft of our schema, I've become a bit paralyzed trying to establish naming conventions that will scale as the product matures. I would really appreciate some insight from anyone who has had to grow a schema and run into, or successfully avoided dead ends or inconsistencies:
Is it generally useful/idiomatic to keep the name "Interface" in the name of an interface? For example, would Profile or ProfileInterface be preferable in a large app?
interface ProfileInterface {
# fields here...
}
type UserProfile implements ProfileInterface {
# implemented fields here...
}
Is it common to specify single-enum values as "constants"?
enum GeoJSONFeatureTypeConstant {
feature
}
interface GeoJSONFeatureInterface {
id: ID
type: GeoJSONFeatureTypeConstant!
geometry: GeoJSONGeometryInterface!
properties: GeoJSONProperties
}
Is it best practice to declare all-or-nothing objects as scalar or type, and where is the line drawn between the two? Imagine a Point type that is would typically be represented as an array [x,y]; which would be more idiomadic?
scalar Point
type Point {
x: Float
y: Float
}
Any other best-practices specifically related to naming conventions or type declarations in GraphQL that would be difficult to know without experience.
Thanks in advance!
This question hasn't gained the momentum I would have liked, so I'm going to start posting useful snippets as I find them, which may evolve into an answer of sorts.
Naming input types with Input on the end is a useful convention,
because you will often want both an input type and an output type that
are slightly different for a single conceptual object.
http://graphql.org/graphql-js/mutations-and-input-types/
I pondered about these same questions and I hope this will be helpful to you.
1. I don't believe that appending Interface at the end of every interface is idiomatic. It is much better to have a descriptive name instead. Consider the example provided in the GraphQL Specification relating to Interfaces. They don't append Interface to any of their types.
2. Enums are only advantageous when there are multiple related values. I don't see how including type is helpful when there is only one possible value. Enum values are also named with all caps and underscores per the GraphQL Specification relating to Enums.
3. If you decided to implement a scalar type then it is up to you to validate the field. In this specific case, providing Point as a type makes the most sense as a Point could be 2-D or 3-D. Defining it as a type is more declarative.
Values such as Date, Email and Url are common examples for scalar types. They provide semantic value and clients will know what to expect from these fields.
Here's the relevant section for custom scalars.
Here's an example.
4. You will find this article by Lee Byron helpful.
I found this graphql API design tutorial from Shopify some time ago. I think there is no explicit chapter but best practice w.r.t. naming convention spread across the tutorial.
Related
At work, I'm involved in maintaining our React component library, which we're very slowly in the process of converting to TypeScript. (But my question is about Typescript more generally and not specific to React - that's just how the question has arisen and how I imagine it might arise for many others!)
Like many such component libraries, we often use a union of string literals as the type for some props, to ensure they always have one of a small number of approved values - a typical example might be type Size = "small" | "medium" | "large";. And while we don't always use a type alias for them as shown there, it is frequent enough that we do, as the type may need to be referred to in a few different places, and it's nice (particularly with larger unions than this) to not have to type out the same thing all the time, as well as knowing that if the design team ever want us to add a new extra-large size or whatever, the type at least will only have to be updated in one place.
This works fine of course, but we've discovered that in terms of intellisense it leaves quite a lot to be desired. We want our consumers, who likely don't know all the valid values off my heart, to be told what these are by their IDE when rendering the component. But by doing this in the most obvious way - ie like this:
type Size = "small" | "medium" | "large";
interface Props {
size: Size;
}
then when consuming the props in any form, IDEs such as VSCode on hovering over the size prop will simply display the rather unhelpful Size as the prop's type, rather than the explicit union of 3 strings which would be far more helpful.
(Note that although the above is using an interface rather than a type alias, which is the way we've decided to go after some debate, the same issue is present when using type for
the props type.)
This seems like it should be a common question, but many searches on google and Stack Overflow have failed to turn anything up that's specific to simple unions of strings.
There are discussions about ways to get TS to "expand" or "simplify" complex types - like this Stack Overflow question and its great answers, or this article, which basically show the same solution although they differ in details. But these seem to be aimed at - and certainly work on - object types specifically. Sadly, no matter which of these transformations is applied to the type of the size prop in the above example, TypeScript still stubbornly shows the unhelpful Size as the prop's type when actually consuming it. (For those for whom this makes sense - Haskell is among my favourite languages - I would phrase this more succinctly as: these solutions appear to work on product types but not on sum types.)
This is demonstrated in this TS playground example - specifically the size2 prop. (This shows only one form of the Expand type, but I've tried every slight variation I've either found online or have come up with myself, with no success.)
The others - size3 and size4 - are attempts at using template literal types based on the same "trick" that is behind the Expand example. I understand they're based on using a conditional type to force distribution of the operation across a union and then making sure the operation is essentially a no-op, so the actual type is still the same but after hopefully forcing TS to compute something across the union to output a "new", "plain" union. Since the Expand type suggested above iterates across keys, fine for an object type with properties but unclear if it has any meaning for a union of string literals, it seemed using a template literal as the operation in this trick was the same idea but adapted to such a union of literal string types. And specifically, concatenating with an empty string is the only obvious way to make this keep the strings as they were.
That is, I thought
type NoOpTemplate<T> = T extends string ? `${T}${""}` : T;
might work. But as you will see from the playground link above (size3 prop), it doesn't.
I even hit upon the idea of using a generic type with two parameters:
type TemplateWithTwoParams<T, U extends string> = T extends string ? `${T}${U}` : T;
This "works" in a sense, because the prop defined as notQuiteSize: TemplateWithTwoParams<Size, "x">; displays as an explicit union as desired: "smallx" | "mediumx" | "largex". So surely supplying an empty string as the U parameter will do what we want here - keep the strings in the union the same, while forcing explicit display of the options?
Well no, it doesn't, as you can see from the size4 prop in the example! It seems the TS compiler is just too clever, as all I can assume is that it spots that in this case we're just concatenating with an empty string, which is a no-op, and therefore doesn't need to actually compute anything and thus outputs the same type T as it was given - even via the type alias.
I'm out of ideas now, and surprised this doesn't seem to be a common problem with clever solutions like the above Expand that I can read about online. So I'm asking about it now! How can we force TS to display a union type as an explicit union, when used as part of an object or interface, while still keeping the convenience of using an alias for it?
It turns out that I was thinking along the right lines, I just needed a different "do-nothing" operation to apply to each member of the union.
Specifically, wrapping the value in an object, and then extracting it, like this:
type WrapInObject<T> = T extends any ? { key: T } : never;
type Unwrap<T> = T extends { key: any } ? T["key"] : never;
type ExplicitUnion<T> = Unwrap<WrapInObject<T>>;
works as intended. Here's the TS playground example from the question expanded with this version - as prop sizeThatWorks, where if you hover to see the intellisense you will see the desired output of the explicit union, rather than the Size alias.
This has a further advantage of presumably working for any union, not just one of string literals. I wish I knew this would continue to work in future versions of the TS compiler - I hate to think that future versions may be "clever" enough to realise that this wrapping-and-unwrapping is a no-op, as apparently happened with my attempts using template literal types. But this seems to be the best available, at least at present.
I am learning Ruby, reading few books, tutorials, foruns and so one... so, I am brand new to this.
I am trying to develop a stock system so I can learn doing.
My questions are the following:
I created the following to store transactions: (just few parts of the code)
transactions.push type: "BUY", date: Date.strptime(date.to_s, '%d/%m/%Y'), quantity: quantity, price: price.to_money(:BRL), fees: fees.to_money(:BRL)
And one colleague here suggested to create a Transaction class to store this.
So, for the next storage information that I had, I did:
#dividends_from_stock << DividendsFromStock.new(row["Approved"], row["Value"], row["Type"], row["Last Day With"], row["Payment Day"])
Now, FIRST question: which way is better? Hash in Array or Object in Array? And why?
This #dividends_from_stock is returned by the method 'dividends'.
I want to find all the dividends that were paid above a specific date:
puts ciel3.dividends.find_all {|dividend| Date.parse(dividend.last_day_with) > Date.parse('12/05/2014')}
I get the following:
#<DividendsFromStock:0x2785e60>
#<DividendsFromStock:0x2785410>
#<DividendsFromStock:0x2784a68>
#<DividendsFromStock:0x27840c0>
#<DividendsFromStock:0x1ec91f8>
#<DividendsFromStock:0x2797ce0>
#<DividendsFromStock:0x2797338>
#<DividendsFromStock:0x2796990>
Ok with this I am able to spot (I think) all the objects that has date higher than the 12/05/2014. But (SECOND question) how can I get the information regarding the 'value' (or other information) stored inside the objects?
Generally it is always better to define classes. Classes have names. They will help you understand what is going on when your program gets big. You can always see the class of each variable like this: var.class. If you use hashes everywhere, you will be confused because these calls will always return Hash. But if you define classes for things, you will see your class names.
Define methods in your classes that return the information you need. If you define a method called to_s, Ruby will call it behind the scenes on the object when you print it or use it in an interpolation (puts "Some #{var} here").
You probably want a first-class model of some kind to represent the concept of a trade/transaction and a list of transactions that serves as a ledger.
I'd advise steering closer to a database for this instead of manipulating toy objects in memory. Sequel can be a pretty simple ORM if used minimally, but ActiveRecord is often a lot more beginner friendly and has fewer sharp edges.
Using naked hashes or arrays is good for prototyping and seeing if something works in principle. Beyond that it's important to give things proper classes so you can relate them properly and start to refine how these things fit together.
I'd even start with TransactionHistory being a class derived from Array where you get all that functionality for free, then can go and add on custom things as necessary.
For example, you have a pretty gnarly interface to DividendsFromStock which could be cleaned up by having that format of row be accepted to the initialize function as-is.
Don't forget to write a to_s or inspect method for any custom classes you want to be able to print or have a look at. These are usually super simple to write and come in very handy when debugging.
thank you!
I will answer my question, based on the information provided by tadman and Ilya Vassilevsky (and also B. Seven).
1- It is better to create a class, and the objects. It will help me organize my code, and debug. Localize who is who and doing what. Also seems better to use with DB.
2- I am a little bit shamed with my question after figure out the solution. It is far simpler than I was thinking. Just needed two steps:
willpay = ciel3.dividends.find_all {|dividend| Date.parse(dividend.last_day_with) > Date.parse('10/09/2015')}
willpay.each do |dividend|
puts "#{ciel3.code} has approved #{dividend.type} on #{dividend.approved} and will pay by #{dividend.payment_day} the value of #{dividend.value.format} per share, for those that had the asset on #{dividend.last_day_with}"
puts
end
I have an angular 1.4 project on typescript, the project is getting bigger and bigger and our team is really tired of interfaces that we have declared (so that all objects are typed, in comparison to any)
I'm asking if this is a good idea or not? I chose typescript because I wanted to have a typed project, should I drop the interfaces or not?
You can get by without using interfaces and going with any, but in the long term you are probably going to regret it. If your team is sick of the interfaces you've created, I would put time in fixing those instead of abandoning them. There is a significant argument around if typed languages reduce the number of errors found in code. Personally, I think they do.
What I've found with typed languages is that it helps remove stupid mistakes we all make, and this clears up our time to focus on actual logic problems in code. Not everyone agrees with me on this, but I will always pick a type language over a non typed one, especially if the team is used to dealing with languages like Java or C#.
Interfaces can be very helpful if used properly.
If you are just doing this....
IFoo { ... }
Foo implements IFoo { ... }
Then they will not help as much as they do in other typed languages (C#/Java). Because the type checking in TypeScript is dependent upon the properties on the object and NOT on the declared type. This is because you can simply write this...
MyCtrl (foo: Foo) { ... }
//instead of
MyCtrl {foo: IFoo) { ... }
This will not hinder unit testing in any way since as stated above the type checking is based upon properties and not declarations.
There are cases when interfaces can be quite helpful, for instance a common use case is when defining an object as a parameter...
doSomething (options: ISomethingOptions) { ... }
There is no harm in creating interfaces for everything, you just need to determine what level of typing works best for your team.
I was explaining to a friend a few days ago the concept or inheritance and containers.
He has very little programming knowledge so it was really just a friendly chat.
During the conversation he came to me with a question that i just couldn't answer.
"Why cant you just have an array of the top level class, and add anything to it"
I know this is a bad idea having being told so before by someone far smarter but for the life of me i couldn't remember why.
I mean we do it all the time with inheritance.
Say we have class animal which is parent of cat and dog. If we need a container of both of these we make the array of type animal.
So lets say we didn't have that inheritance link, couldn't we just use the base object class and have everything in the one container.
No specific programming language.
Syntactically, there is no problem with this. By declaring an array of a specific type, you are giving implicit information about the contents of that array. You could well declare a contain of Object instances, but it means you lose all the type information of the original class at compile-time.
It also means that each time you get an object out of the array at runtime, the only field instances and methods you know exist are the fields/methods of Object (which arguably is a compile time problem). To use any of the fields and methods of more specific subclasses of the object, you'd have to cast.
Alternatively, to find out the specific class at runtime you'd have to use features like reflection which are overkill for the majority of cases.
When you take elements out of the container you want to have some guarantees as to what can be done with them. If all elements of the container are returned as instances of Animal (remember here that instances of Dog are also instances of Animal) then you know that they can do all the things that Animals can do (which is more things than what all Objects can do).
Maybe, we do it in programming for the same reason as in Biology? Reptiles and Whales are animals, but they are quite different.
It depends on the situation, but without context, it's definitely okay in most (if not all) object-oriented languages to have an array of a base type (that is, as long as they follow all the substitution principles) containing various instances of different derived types.
Object arrays exist in certain cases in most languages. The problem is that whenever you want to use them, you need to remember what type they were, and stay casting them or whatever.
It also makes the code very horrible to follow and even more horrible to extend, not to mention error prone.
Plant myplant = new Plant();
listOfAnimals.Add(myplant);
would work if the list is object, but you'd get a compile time error if it was Animal.
What distinguishes and object from a struct?
When and why do we use an object as opposed to a struct?
How does an array differ from both, and when and why would we use an array as opposed to an object or a struct?
I would like to get an idea of what each is intended for.
Obviously you can blur the distinctions according to your programming style, but generally a struct is a structured piece of data. An object is a sovereign entity that can perform some sort of task. In most systems, objects have some state and as a result have some structured data behind them. However, one of the primary functions of a well-designed class is data hiding — exactly how a class achieves whatever it does is opaque and irrelevant.
Since classes can be used to represent classic data structures such as arrays, hash maps, trees, etc, you often see them as the individual things within a block of structured data.
An array is a block of unstructured data. In many programming languages, every separate thing in an array must be of the same basic type (such as every one being an integer number, every one being a string, or similar) but that isn't true in many other languages.
As guidelines:
use an array as a place to put a large group of things with no other inherent structure or hierarchy, such as "all receipts from January" or "everything I bought in Denmark"
use structured data to compound several discrete bits of data into a single block, such as you might want to combine an x position and a y position to describe a point
use an object where there's a particular actor or thing that thinks or acts for itself
The implicit purpose of an object is therefore directly to associate tasks with the data on which they can operate and to bundle that all together so that no other part of the system can interfere. Obeying proper object-oriented design principles may require discipline at first but will ultimately massively improve your code structure and hence your ability to tackle larger projects and to work with others.
Generally speaking, objects bring the full object oriented functionality (methods, data, virtual functions, inheritance, etc, etc) whereas structs are just organized memory. Structs may or may not have support for methods / functions, but they generally won't support inheritance and other full OOP features.
Note that I said generally speaking ... individual languages are free to overload terminology however they want to.
Arrays have nothing to do with OO. Indeed, pretty much every language around support arrays. Arrays are just blocks of memory, generally containing a series of similar items, usually indexable somehow.
What distinguishes and object from a struct?
There is no notion of "struct" in OOP. The definition of structures depends on the language used. For example in C++ classes and structs are the same, but class members are private by defaults while struct members are public to maintain compatibility with C structs. In C# on the other hand, struct is used to create value types while class is for reference types. C has structs and is not object oriented.
When and why do we use an object as opposed to a struct?
Again this depends on the language used. Normally structures are used to represent PODs (Plain Old Data), meaning that they don't specify behavior that acts on the data and are mainly used to represent records and not objects. This is just a convention and is not enforced in C++.
How does an array differ from both,
and when and why would we use an
array as opposed to an object or a
struct?
An array is very different. An array is normally a homogeneous collection of elements indexed by an integer. A struct is a heterogeneous collection where elements are accessed by name. You'd use an array to represent a collection of objects of the same type (an array of colors for example) while you'd use a struct to represent a record containing data for a certain object (a single color which has red, green, and blue elements)
Short answer: Structs are value types. Classes(Objects) are reference types.
By their nature, an object has methods, a struct doesn't.
(nothing stops you from having an object without methods, jus as nothing stops you from, say, storing an integer in a float-typed variable)
When and why do we use an object as opposed to a struct?
This is a key question. I am using structs and procedural code modules to provide most of the benefits of OOP. Structs provide most of the data storage capability of objects (other than read only properties). Procedural modules provide code completion similar to that provided by objects. I can enter module.function in the IDE instead of object.method. The resulting code looks the same. Most of my functions now return stucts rather than single values. The effect on my code has been dramatic, with code readability going up and the number of lines being greatly reduced. I do not know why procedural programming that makes extensive use of structs is not more common. Why not just use OOP? Some of the languages that I use are only procedural (PureBasic) and the use of structs allows some of the benefits of OOP to be experienced. Others languages allow a choice of procedural or OOP (VBA and Python). I currently find it easier to use procedural programming and in my discipline (ecology) I find it very hard to define objects. When I can't figure out how to group data and functions together into objects in a philosophically coherent collection then I don't have a basis for creating classes/objects. With structs and functions, there is no need for defining a hierarchy of classes. I am free to shuffle functions between modules which helps me to improve the organisation of my code as I go. Perhaps this is a precursor to going OO.
Code written with structs has higher performance than OOP based code. OOP code has encapsulation, inheritance and polymorphism, however I think that struct/function based procedural code often shares these characteristics. A function returns a value only to its caller and only within scope, thereby achieving encapsulation. Likewise a function can be polymorphic. For example, I can write a function that calculates the time difference between two places with two internal algorithms, one that considers the international date line and one that does not. Inheritance usually refers to methods inheriting from a base class. There is inheritance of sorts with functions that call other functions and use structs for data transfer. A simple example is passing up an error message through a stack of nested functions. As the error message is passed up, it can be added to by the calling functions. The result is a stack trace with a very descriptive error message. In this case a message inherited through several levels. I don't know how to describe this bottom up inheritance, (event driven programming?) but it is a feature of using functions that return structs that is absent from procedural programming using simple return values. At this point in time I have not encountered any situations where OOP would be more productive than functions and structs. The surprising thing for me is that very little of the code available on the internet is written this way. It makes me wonder if there is any reason for this?
Arrays are ordered collection of items that (usually) are of the same types. Items can be accessed by index. Classic arrays allow integer indices only, however modern languages often provide so called associative arrays (dictionaries, hashes etc.) that allow use e.g. strings as indices.
Structure is a collection of named values (fields) which may be of 'different types' (e.g. field a stores integer values, field b - string values etc.). They (a) group together logically connected values and (b) simplify code change by hiding details (e.g. changing structure layout don't affect signature of function working with this structure). The latter is called 'encapsulation'.
Theroretically, object is an instance of structure that demonstrates some behavior in response to messages being sent (i.e., in most languages, having some methods). Thus, the very usefullness of object is in this behavior, not its fields.
Different objects can demonstrate different behavior in response to the same messages (the same methods being called), which is called 'polymorphism'.
In many (but not all) languages objects belong to some classes and classes can form hierarchies (which is called 'inheritance').
Since object methods can work with its fields directly, fields can be hidden from access by any code except for this methods (e.g. by marking them as private). Thus encapsulation level for objects can be higher than for structs.
Note that different languages add different semantics to this terms.
E.g.:
in CLR languages (C#, VB.NET etc) structs are allocated on stack/in registers and objects are created in heap.
in C++ structs have all fields public by default, and objects (instances of classes) have all fields private.
in some dynamic languages objects are just associative arrays which store values and methods.
I also think it's worth mentioning that the concept of a struct is very similar to an "object" in Javascript, which is defined very differently than objects in other languages. They are both referenced like "foo.bar" and the data is structured similarly.
As I see it an object at the basic level is a number of variables and a number of methods that manipulate those variables, while a struct on the other hand is only a number of variables.
I use an object when you want to include methods, I use a struct when I just want a collection of variables to pass around.
An array and a struct is kind of similar in principle, they're both a number of variables. Howoever it's more readable to write myStruct.myVar than myArray[4]. You could use an enum to specify the array indexes to get myArray[indexOfMyVar] and basically get the same functionality as a struct.
Of course you can use constants or something else instead of variables, I'm just trying to show the basic principles.
This answer may need the attention of a more experienced programmer but one of the differences between structs and objects is that structs have no capability for reflection whereas objects may. Reflection is the ability of an object to report the properties and methods that it has. This is how 'object explorer' can find and list new methods and properties created in user defined classes. In other words, reflection can be used to work out the interface of an object. With a structure, there is no way that I know of to iterate through the elements of the structure to find out what they are called, what type they are and what their values are.
If one is using structs as a replacement for objects, then one can use functions to provide the equivalent of methods. At least in my code, structs are often used for returning data from user defined functions in modules which contain the business logic. Structs and functions are as easy to use as objects but functions lack support for XML comments. This means that I constantly have to look at the comment block at the top of the function to see just what the function does. Often I have to read the function source code to see how edge cases are handled. When functions call other functions, I often have to chase something several levels deep and it becomes hard to figure things out. This leads to another benefit of OOP vs structs and functions. OOP has XML comments which show up as tool tips in the IDE (in most but not all OOP languages) and in OOP there are also defined interfaces and often an object diagram (if you choose to make them). It is becoming clear to me that the defining advantage of OOP is the capability of documenting the what code does what and how it relates to other code - the interface.