Designing Wonderful .NET APIs
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Newton-King, James
There are .NET libraries that are complex to setup, hard to understand, difficult to debug, and impossible to extend. And then there are .NET libraries for the same task that wonderfully just work. Why do some libraries succeed where others fail? In this session James will discuss what makes a well designed API, from high level design principles like The Pit of Success, The Wall of Complexity, and The Power of Sameness, to applying those concepts in low level .NET class design, with the goal of creating .NET libraries that developers love to use.
 Hello. Are we good? Can anyone hear me? Awesome. OK, so we'll get started. So hello, everyone, and welcome to the session. It's wonderful.donate API design. So we'll get started with some introductions. So my name is James Huydon-King. I'm from Wellington, New Zealand, all the way down there. And I've been a Donate developer for a little over 10 years. If you're familiar with Flight of the Concords, they have some wonderful demotivational photos about posters about New Zealand. It's a lot further, having just flown on a couple of days ago. So probably what I'm best known for, about eight years ago, I started a project called JSON.NET. And from that project, I've gained, and just from regular Donate development, I've gained quite a bit of knowledge about API design. And I think it's a little known skill that's talked about amongst Donate developers. There's been a lot of focus on REST API design. I think it would be good to focus a bit on Donate API design. So to get started first, what is Donate API design? What is a Donate API? So really an API is types, it's properties, it's methods. So it's the members almost types, it's constructors, it's perhaps more Donate specific constructs like events. It's really the code that you interact with when working with a library. And API design is really about communicating what an API does. If you could stand over the shoulder of every single developer who was using your code, you wouldn't need to worry about API design because you could just tell them. But because you're not there, you need to create APIs that are able to communicate to users. Yes, so communicating to developers. So imagine, so we'll give a little example. Imagine we've got some code here. We're connecting to a database. We're getting a count from a database table, and then we're returning that. The problem with this code is we're creating a connection to a SQL database, but we're not closing it. The way as an API designer, you communicate to a user that there is a resource that they need to clean up is you make it implement iDisposable. As soon as you implement iDisposable, that developer should be able to see that this is something that they need to clean up. And if they don't already know that, then hopefully either Visual Studio or a tool like Resharpid does tell them. And when they see that they need to clean that code up, they'll just change their usage of the API. So in this case, it's the SQL database API, and close their connections and fix their code. So it's all about creating code which communicates to developers how they should use it. So why is API design important? So it's potentially the difference between an API that discourages users, waste their time through them going through trial and error, having to look at documentation, and a good API which is creating productive and happy users. API design is also important because APIs are forever. So ideally, any API, so any code which is designed to be reusable, shouldn't change. So I've got a little star against APIs are forever, because there's sort of like a range of how much change you're able to do to an API. If an API is for internal use only, so really you're just referencing another project, and perhaps it's a reusable data layer to talk to your database, then it's pretty easy to change. If you rename something, and there are perhaps a method, then Resharpher or Visual Studio will automatically rename it throughout Visual Studio, throughout the rest of your solution. If you're shipping a DLL within your company, that's perhaps slightly more problematic when making changes. If you're publishing a framework on Nougat, that's harder still, because you aren't able to immediately communicate to your users that the API is broken. The worst case scenario is if you're publishing a Nougat package, and then that Nougat package is dependent upon other Nougat packages, you make a change which breaks other Nougat packages. Anyone who uses those Nougat packages is broken until those other library authors go and update their own packages. So the worst case scenario happens to be my own library, json.net. So this was created by a developer, a program manager, on the Nougat team. And at the bottom of an inverted stack of cards is json.net. If I make a breaking change, then I could potentially break hundreds, maybe even thousands, of other Nougat libraries. 1,500 other Nougat libraries depend upon json.net. So when you get to that sort of scale, APIs really are forever. And you make a breaking change to a low-lying library like json.net or the.NET framework, you're going to create a lot of unhappy developers. And the thing about APIs is every piece of code that uses that API in its current form is an investment in it. If you're breaking APIs, you're destroying that investment in that API. API design is important because everyone really is an API designer. Code should not just be maintainable. Ideally, it should be reusable. So you want to aim for dry. Don't repeat yourself. So really, when you're designing APIs, this might be your payment service within your own solution. These are some.NET classes, methods, properties. This is an API. You want to think about reusability. So thinking about API design encourages good programming. So what makes a good API? A good API should be both easy to learn and easy to use. So easy to learn. It should be consistent with the platform. If you're working in the.NET environment, if you're publishing a.NET package, you should follow the.NET naming standards. You should use.NET constructs. Like if you're communicating with the file system, you should talk to streams. You shouldn't invent your own way to talk to the file system. A good API should be consistent with itself. If you're doing two tasks and two separate places, you should do those two tasks the same way. You shouldn't unnecessarily complicate and confuse things for your users. And a good API should be easy to use. So it should be well-named. You want to aim to make it as strongly typed as possible. Ideas are fantastic. Visual Studio, amongst Tony developers, is fairly ubiquitous. IntelliSense is awesome. So strong naming is strongly typed classes are your friends, it helps with IntelliSense. So with the easy to use, you also conversely want it to be hard to misuse. So for example, if a user does something wrong and they do a set something to a bad value, you want to validate that and throw an error quickly and tell them that they've done something wrong. So perhaps an example of some bad classes, a bad API with them in the.NET framework, is this code. So just immediately looking at it is not following the.NET naming standards. Imagine if you will that these were constants instead of enumeration. So enum provides a great strongly typed way of telling a user what values are available. So you'll get a compile error otherwise. This code is invented its own way to talk to a file system. It's using its own custom file adapter rather than just taking the built-in.NET stream. And it's using setters instead of properties. So it's not using the built-in.NET, well, in this case, C-sharp language features. So this might be an example of a Java API that someone's ported directly to.NET without putting in the time and effort to make it easy to use within the.NET environment. And I don't know about you, but if I came across having to use this sort of library, I'd be very upset. It's not pleasant code to use. If anyone's ever used a Java port to.NET, it's not a pleasant experience. So a good API should also encourage code that uses it to be easy to understand and maintain. So an example I can think of that is imagine this is an in-hybernate mapping class, or mapping configuration XML file. So in-hybernate is a.NET ORM. This piece of XML is mapping a.NET type to a database table, and that's what it does. The problem with encouraging code like this, in this case, XML, is it's verbose. You're having to go in. You're manually typing it, and it's brittle. It's not strongly typed. If you rename your.NET class, then this is going to break until you run. If you compare that to something like using just plain attributes, this.NET class with attributes, it's reusing the property names rather than having to specify them manually like you were in the XML. By placing a property on an attribute on a property, you're going to immediately use both that property name. You can use that type, likewise with the ID. So this sort of pattern is like convention over configuration, and it's sort of leveraging the built-in type that you're already using rather than having to duplicate all the mapping information in a XML file. And it's leading to code which is both easy to use and understand and maintain. You want to create APIs that are sufficiently powerful to meet requirements, but not overly powerful. So when designing APIs, there's often a conflict between two separate worlds, there's creating both API that is powerful enough to meet the needs of a broad range of developers, but is still simple for users who just need a small subset of it. So when you're designing an API, you just need to be careful that you don't ruin simplicity by being overly powerful. A good API can also evolve. So bugs can be fixed, features can be added without making breaking changes. So a good example of that is the.NET framework. So it's maintained compatibility pretty well over the years, while still being able to add lots of new features. So now we'll talk about a bunch of general API design principles. And perhaps the most important principle is the pit of success. So this is a term that was coined by an employee at Microsoft. So the pit of success. In stark contrast to a summit, a peak, or a journey across a desert to find victory through many trials and surprises, we want our customers to simply fall into winning practices by using our platforms and frameworks. To the extent that we make it easy to get into trouble, we fail. So success shouldn't be climbing a mountain. Users shouldn't need to figure out how to make complex configuration files or understand complex processes. It shouldn't be like trekking across a desert. You shouldn't need to write tons of boilerplate code to successfully do a task with an API. You shouldn't have to wade through tons of documentation, tons of methods and settings on many different classes to find what you want. Success should be as simple as falling into a pit. So the goal when you're designing APIs is to make it easy to succeed and hard to fail. And hopefully we'll look at a whole bunch of ways of doing that throughout the rest of our presentation. Another general principle is the wall of complexity. So the wall of complexity is the idea that your API should offer a steadily increasing slope of difficulty as their usage becomes more complex. So if your user is suddenly requiring a huge increase in knowledge or a huge increase in efforts to perform an additional minor task, that's an example, perhaps, of them running into a wall of complexity. So imagine you have an amazing form and suddenly you need to do a specific bit of custom validation and what you expected to take 30 minutes takes two days. That's an example of you hitting a wall of complexity. And chances are when a user hits a wall of complexity, they're going to fail. And they're not going to have a pleasant experience. It's great, isn't it? So an example of a framework that I think hits a wall of complexity is the good old ASP.net web forms. So web forms was advertised as a way of creating rich web pages on the server using simple drag and drop into an IDE, double click on a button, and suddenly you've got an event and everything's nice and simple. The problem with web forms is if you need to suddenly start performing even moderately complex tasks, if you need to perform even moderately complex tasks, you suddenly hit this enormous wall of complexity. Of all this knowledge, you suddenly need to understand about the ASP.net lifecycle and the web form page lifecycle, all the events that happened. So this is like a diagram showing all the different events that can be raised off a web form's web page. So you need to know when the post-back happened, when data binding happened, when rendering happened. So for me, I always hit this problem when suddenly you needed to post-back values to data bounds, drop downs, and a repeating list. And suddenly you need to worry about what's going to happen, and suddenly you need to worry about what order you bound the list, what order the post-back values were applied to this list. It all became very complex. And all from a framework which is advertised as something which is meant to be just drag and drop and double click and you're done. So a framework which did it better, in my opinion, is the MVC. So obviously MVC, it requires you to have some knowledge of HTML and have some knowledge about HTTP. But it's really a steadily sloping increase of difficulty as you do more and more complex tasks. If you need to suddenly do complex Ajax callbacks and you have complex JavaScript, well, that isn't suddenly orders of magnitude more difficult than what you're currently doing. MVC provides nice hooks for you to add in complexity, but you only need to hook them in when needed. An example of a framework which does this wall of complexity really badly, and it's almost an anti-pattern, is WCF. So WCF puts all the complexity up front, even if you're doing a very simple task, like you want to have a basic HTTP service and you want to give it some XML and get some XML back. There's all this configuration. There's all this knowledge, all this learning that you need to understand, especially the configuration. I could never get it right. And you need to all understand that all up front. And it's not a great framework. So the next general principle is the power of sameness, which sounds kind of weird. It's a term coined by a guy called Brad Abrams. And he's a ex-Microsoft employee. And the idea of the power of sameness is by creating APIs that use features that developers already know, developers can quickly achieve tasks because they already know how to do it. An example, and this is the example that he uses, is that of interacting with the car. No matter what car you're working with, well, you're in, whether it's a taxi, it's your friend's car, it's your own car, it's a car you're renting, door locks tend to work the same way. If you're confronted with a door and you need to unlock it, chances are you don't need to ask for help. You don't need to read an instruction manual because they tend to work all exactly the same way. And that's the power of sameness, likewise with a seatbelt. All seatbelts tend to work the same way. So if we imagine that within the context of a.NET API, you want to use naming standards that everyone's familiar with. You want to use common types and interfaces like I dispose of at everyone's familiar with stream. You want to use configuration patterns that people are familiar with. So you want to use web config, app config, to put configuration rather than your own custom files. By using these techniques that developers already know about, you're helping them fall into a pit of success. They already know how to do these things, so they don't need to learn them again just for your own API. So when you're starting out designing an API, probably one of the most important things is you want to start small. You want to start small because you want to firstly provide a solid foundation, but also because you want to release quickly. You want to release quickly because at least initially you're just guessing how your API is going to be used. You don't know exactly all the different ways developers could potentially use your API. So the sooner you release, the sooner you can start getting feedback. And by starting small, you're minimizing potentially the amount of changes that you need to make. So if you've already made mistakes, the number is smaller. What you want to think about with this is incremental improvement is better than delayed perfection. And that's especially important because your idea of perfection could be quite different than what your user's idea is. You want to listen to user feedback. But when listening to user feedback, you need to be able to decipher what users say versus what they mean. So users will tend to suggest for features, specific features that solve their problem and perhaps don't address other people's problems. So imagine if you will, you had a custom list class. It has some strings in it. And you had a method to sort. A user of your API will tend to come along and suggest, what you need is a new method that sorts in exactly this way that I want it to sort. And what you could do is you could add a new method on. Crazy user sort. It implements a sort for them. And that's what they've suggested. But while that works for them, it doesn't work for other developers. So you would need to, each new developer who uses your API might come along and request a new sort mechanism. That's bad, both because it's putting lots of work on you. And it's bad for your users because they're waiting for you to add new sorting methods. So you don't want to do that. What you really want to listen to is what they mean. What they mean is they want a way to be able to customize the sort, and they want a way to be able to do it themselves. So this is an example from the.NET list class. And it has a sort function on it that takes a comparable delegate. The delegate takes two values. And then within it, you can hook in your own custom comparison logic and then sort it yourself. And by doing this, you've created a mechanism that works not just for the developer who said they needed a way to do custom sorting. It works for all users of your API. So as well as positive feedback, you can also get negative feedback. And just because it's negative feedback, it doesn't mean you don't want to listen to it. So there's this quote from Benjamin Franklin. Critics are our friends. They show us our faults. So it might be a user complaining on Twitter about how horrible something is. But you want to think about what they say and think, is there a way I can solve their problem for them? So expect to make mistakes, especially at the start. So your initial release, you're really just guessing what users want and how they'll use your API. So it's quite easy for you to make mistakes. And you should pretty much expect to do so. So the way you can get around this is starting small and releasing often. So that both minimizes the amount of changes that you'll make, so the mistakes that you've made, they've been minimized. And that whole releasing early and often incremental improvement. If you do make a mistake, don't be afraid to make types and members obsolete. So to do that, within the.NET framework, you place an obsolete attribute on a member that will show up in tele-sense. It will be crossed out. So all new users won't use it. And any existing users of your API, when they recompile, they'll get a compiler warning. And within that attribute, you can provide a description of what they should do instead. Not all feature suggestions are good. And also not all pull requests, if you've got your source code on something like Git, is good. Don't be afraid to say no if you don't think it's a good feature. With features, you want to think about quality over quantity. You want to focus on doing a good job for the most users possible. And if you can help those perhaps non-normal use cases without hurting your core users, then that's great. Perhaps accept those pull requests. But otherwise, don't be afraid to say no if you don't think it's appropriate for most users. So those are the general principles of API design. So the rest of the presentation, we're going to focus on lower level API design and how it relates specifically to.NET. So the.NET framework has extensive naming guidelines. And for the most part, unless you've got a very good reason otherwise, you should always follow them. So the first one is always Pascal case, namespaces, types, and delegates. So Pascal case, as you can see on that slide, each word should start with a capital letter. You also want a Pascal case, methods, properties, fields, and events. And you want a camel case parameters. So the.NET naming guidelines are pretty simple. Pascal case, everything except parameters to methods or constructors, and camel case those. You'll note in this code, I have a private field and it's starting with an underscore. The naming guidelines are really just for public members and public types. Anything private or internal, users won't see anyone who's interacting with your API won't see. So you can name those however you want. I've always done an underscore on my private fields. But yeah, whatever you want. One interesting rule that a lot of people don't follow is you want to always Pascal case acronyms that are three letters and longer. So some examples. In the.NET framework, it is an XML document with XML all uppercase. It's XML document with XML Pascal case. Likewise, HGB client. But then if it's only two letters, so in this case, IO exception, you can leave those both as capitals. Some additional tips when naming your types of members. You want to avoid acronyms. So a good way to test whether an acronym is acceptable is just go to Google. And if lots of people are referring it to it by the acronym, so if people are talking about HTML rather than Hypertext markup language, then the acronym is great. Avoid abbreviations. Well, I'd say even stronger. Don't abbreviate. So IDEs these days. So Visual SEO, you have auto complete. Typing, writing code, that's fast. You write code once. You read it dozens of times. So you want to make your API optimized for readability rather than quickly writing it within reason. So that will help avoid developer confusion when reading your APIs. So a bunch of other random tips. So interfaces, start those with deny. Generic type parameters, start those with a T. So in the case of dictionary, a generic dictionary, it takes T key and T value as its generic types. And then there's a bunch of.NET types that when you inherit from them, you should always suffix with a certain bit of text. So attributes should always end with attributes. If you're implementing your own custom exception class, it should always end with exception, stream with stream, and so on. So interface and abstract base class design is interesting. So there's a bunch of common pitfalls that people make when implementing interfaces and abstract base classes while designing them. So the first one is they put too many methods on an interface or an abstract base class. So the canonical example, the one that I always think of, is the old membership provider in ASP.NET. So all these types, and all these properties, are declared as abstract on this base class. And whenever you implement it, you need to implement all of them. So quite often, I've needed to implement this to plug it into some other application. And all I needed to do is to do validation. And all I end up implementing is if you can read it closely, there's a validate user there and a get user. So those were the only ones that the other framework was using. But because this base class had all these abstract members on it, I had all these additional methods. And I just had to leave them as not implemented exceptions, throwing not implemented exceptions. So if you're familiar with SOLID, this is an example of the interface segregation principle. So you want to keep your interfaces small and focused, and likewise with your base classes. So the other common pitfall is having a method that is impossibly complex to implement. So a good example of this with the MedotNet framework is Iquariable. Iquariable takes has just a couple of methods on it that you need to implement. But one of them takes an expression tree. An expression tree can be an expression tree of any expression. And really, Iquariable needs to be able to handle any expression given to it. But really, there's actually only one proper implementation of a link provider. And that's link over in memory data structures. Every other link provider, like NT Frameworks link provider, if you give it a certain expression, it's going to fail. So I'm not saying in this case Iquariable was bad for this specific case, but it's something you want to keep in mind. Have you got a method on your interface or abstract base class that is just impossible for the average person to properly implement? So also with abstract base class design and interfaces, you want to provide an implementation, and you want to provide consumers of this implementation. By doing this, you're ensuring that you've thought about how your interfaces or base classes should be used. So an example I can think of in the.NET framework of where this wasn't done is Iquariable. So Iquariable shipped in.NET 1. And some classes implemented Iquariable, but no APIs actually consumed Iquariable. And unfortunately, the Iquariable description of how it should work is a bit ambiguous. Like should Iquariable clone just the current object? And not as child object? Should it clone all its child objects? Do all its child objects then need to implement Iquariable before they can be cloned? And because it wasn't properly defined how it should work, and because no one actually used it in the.NET framework v1, it's sort of become this orphaned interface that's never been used. And because it's already in there, it can't really be reintroduced now and done properly because it's been taken up. So this would be a case of something which perhaps should have been left out, and then added if needed at a later date. And because it's never used, it's forever alone. So structs are interesting. So structs are similar to classes. You can do a lot of the same things you can with classes. The difference between structs and classes is that structs aren't allocated on the heap. They're value objects. They're on the stack. And because of that, there's no need to allocate them or garbage-click them. So they have some potential performance benefits. But there's only a certain number of circumstances when you want to use a struct. Because they behave subtly different to classes, and users generally expect something to work like a class, you want to use it only when performance is important. They represent, the struct will represent a single value. The struct is small. So the difference between a struct and a class reference when you're passing around is a class reference. So as reference to a class that's sitting on the heap is the reference will always be the exact same size no matter how big the class is. The difference with a struct is because when you're passing around and assigning it to variables, you're passing around the entire struct. If your struct has hundreds and hundreds of fields on it, and it's potentially quite large, you're going to use up a lot of memory each time you create a new one, or you pass it to a method. So for those reasons, you want to only use a struct when you have a small number of fields. So the rule of thumb that the Microsoft guidelines recommend is under 16 bytes. So if the number of bytes of your field, so if you've got ints and floats on there, if they are greater than 16 bytes and you probably want to stick with the class, you also always want your structs to be immutable. You can get some really odd behavior because they're stack allocated when they get boxed. So if you assign it to an object reference, that.NET framework will box it. And if you then make modifications to that box struct, it won't flow through to other places. It's as complex the situations where it can happen. And for that reason, you should really only use structs which are immutable. Struct should also only have a valid empty state. So because they're stack allocated, the default value isn't null. The default value of a struct is a struct with all its fields with a default value. So if you, for example, create an array of structs, each of the elements in that array won't be a null value. It will be an empty struct. So it'll be a struct with its default value. So for example, the datetime in.NET, its default state is 0, 0, 0, 0, 0, 0. And decimal, which is another example of a struct within.NET, its default value is 0. So you need to think about having a valid empty state. And finally, a struct should implement iequitable. Because structs aren't reference objects, when.NET compares the two of them, it isn't as simple as comparing two references and seeing whether they point towards the same object. What.NET does is it will use reflection to reflect over all the structs' fields and compare them one by one, which is quite slow. So you want to manually implement iequitable yourself. So this is just a quick example of a struct done well. So thanks for notice. The fields are immutable. So we've got a constructor, which is assigning those fields. And also down there, we've implemented our own equitable. So equitable is quite simple. It's just an equals method, which takes the same type as itself. And then within there, you can manually do your comparisons. So structs are great for performance, but you just want to be careful about how you use them. So designing enums. Enums are great for closed sets of choices. It allows you to strongly type a choice. And by strongly typing it, you're giving users IntelliSense, you're giving them documentation. So a great example of a struct, I mean a struct, an enum, is Day of Week. It's small, it's constrained, it's not going to grow. A bad example might be Windows version. Microsoft's constantly releasing new versions of Windows, it's constantly releasing new service packs. Every time you release a new version of your framework, you just going to have to add more and more Windows versions. This might be a case where a better choice might be using integers represent a version. With enums, you want to provide a value for zero. Again, they're value types. The default value of enum is zero. And you just want to provide a named value for that. So in the case of string split options, this is an enum with a.NET framework. Its default value is none. The first enum value in this case is always zero. Then the next one will be one. Unless you provide numbers yourself, it will always start at zero. So an enum can support having multiple values at once. And the way you do this is by specifying the flags attribute on that enum. So this is an example from JSON.NET of a flags enum. It's got the flags attribute on it. And then what you need to do for each value within the enum, and unfortunately there aren't more of them on this. And otherwise you'd see a cleaner is you should always go by powers of two. So you should always start with zero, then one, then two, then four, then eight, then 16, and 32. By doing that, you are able to then give users the option to and those options together. So that way a user can say a value should enable reserve reference handling both for objects and arrays by anding those two enums together. And in this example, within a flags enum, you can do that yourself. So all, for example, is an example of objects and arrays being added together. Well, in this case, odd. So with methods, you want to provide descriptive parameter names. Not only do they appear in an IntelliSense, in the latest version of C-Sharp, you can also have named them as named arguments. So by giving descriptive parameter names, it can be the difference between a user quickly and easily using a method and succeeding or having to ask for help, because they don't understand how it should be used. So this is an example of just helping them fall into a pit of success. With methods, you want to have a consistent parameter overload order. So you don't want to confuse developers by mixing around the orders, the order of arguments, the parameters that the method overloads takes of arguments. So an example, this isn't a terribly good example, because this is actually constructors. But this is from within the Donet framework. It's an example of mixing up the order of the same parameters, but just in different orders. So the one down the bottom, pretty much every other exception in.NET will always take message as the first argument. But argument null exception is the one exception in the entire.NET framework. It takes a pram name first. And quite often, you see developers getting them wrong order. And then the description when argument null exception is thrown is a little weird, because it gives the message as the parameter that's null and then the parameter name as the message. When you're designing methods, you want to prefer enum over boolean parameters. So an enum parameter with a descriptive name is much more obvious in what it does than a boolean parameter. So an example, we've got two overloads here. We've got an equals, which takes two strings and a boolean and equals, which takes two strings and an enum. So in that first overload, it isn't immediately obvious what that true is doing. Is that true to ignore case? Is that true to ignore culture? Is that true to trim whitespace from the beginning and the end of the string that we're passing in? It's not immediately obvious. Well, with the second overload, the one which takes the enum, straight away a user can immediately understand what exactly that's doing. So that's why you want to just prefer enums over booleans for parameters when you can. And even if you just have two. So even if you could use true false, it's a lot easier if you just define an enum. You want to avoid out and ref parameters. So this example, when someone wants to call this method, so they're passing in an assembly path and they're getting out a title, they're getting out a description, and they're getting out a company for that assembly. They need to define all these arguments before they can call your method, and then they pass them in. Much easier for a user to just use a method which returns one type. So just create your own object, assign the values to it, and return that. And it's much easier for users to use. Don't be afraid to create helper methods. So a goal of the pit of success is to prevent users from making mistakes. So anytime you have boilerplate code that's repeated over and over within your application, whenever someone potentially needs to use an API, think about wrapping that up in a helper method. So by wrapping, having to create a string reader and then creating a JSON text reader which uses a string reader, then having a schema resolver and a schema builder, it's much easier. Really, all the user is passing in as a string, and they're expecting to get back this JSON schema object. So by creating a helper method, we've eliminated the need for a user to firstly know to create this boilerplate code to potentially make mistakes in it. And we're helping them fall into that pit of success. So properties are quite interesting. So although internally, properties are really just methods, users expect properties to act like fields. And you should strive when possible to meet what users expectations. So the first thing users expect about properties is they should be fast. So imagine we've got this DB context object, and we've got a products property on it. And each time you call dot products, it's going off to the database and loading all the products out of the database. And then imagine the users put it in a loop, and there's 100 products. They're going to load every single product from a database 100 times. Now a user probably wouldn't expect that from a property. They'd expect it to be fast and instant and have very little or no time or overhead. They'd probably certainly wouldn't expect it to call off to a database. So imagine you changed that to a method. So immediately, this looks a bit more suspect. If you saw code which was doing this, you would think about, am I doing that the right way? And methods convey the expectation that there's potentially work is going to go on inside this method. The method might be slow. So you probably want to case your result once and then use that. So by not using a property in that case, by using a method instead, you're encouraging users to use the code more correctly. Also with properties, the result should be consistent. So you don't expect fields to suddenly change. Properties probably shouldn't change either. So imagine we had this a Goode object and on it we had new Goode. So new Goode generated a new Goode. That's probably not quite correct. What's probably a better way to do it is have it as a method. Just like you can't have set only fields, you probably shouldn't have set only properties, even though Donet allows you to do it. So imagine we had a user class and we had a password property on it, but it was set only. And when we set that password property internally, we would hash it and we'd assign that to a field. That's a little weird to use. When they see that there's a password property on a user, they'll probably expect they both be able to assign to it and get a value from it. So in this case, if you don't want to use it to be able to access the result, just change it to a set only property. And users would be much less confused. So for constructor design, constructors should be lazy. Where possible, you want to defer work until it is needed. So imagine in this case, we've got an XML file object. And it's got a constructor on it, which takes a path. And then within the constructor, we're going off to the file system, we're loading that file into an X document, and we're assigning it. And then when someone calls getXML, then we actually return that X document. Imagine then that someone had this little link statement. So they were getting all the XML files on the C drive that ended with XML. They loaded them in. They instantiated these XML files. And then they signed that to a list. Imagine further that a user then only uses maybe one or two of those XML file objects. Even though they've only used one or two, you've still gone off to the disk and loaded hundreds of files potentially. So what you want to do instead is make it lazy. So you want to defer the work only until it's needed. And constructors should really just be about initializing private fields from parameters. So in this case, we're now just assigning path to its own string. And then within getXML, at that point we do the work. And because we probably still want getXML to be fast, we cache the XML document. So we now get the best of both worlds. We still get our own custom XML file class, which has got our business logic. But we're deferring the work until it's needed. With Constructor Design, this one isn't terribly important. But all you're doing is you're setting a field from a parameter. Just make the property name match the same name as the parameter. It just helps users understand what's going on more readily. So one interesting thing about Constructors, and this is something a lot of people don't know, is you want to avoid calling virtual members within a Constructor. So imagine we have this parent class. And it's got a Constructor, which calls doSomething. DoSomething is virtual. We then create a child class that inherits from parent. Within its Constructor, we assign a message. And then in doSomething, we use that message field. Now there's a problem here. The problem is the order of which Constructors are called. The parent constructor is called before the child constructor. But when doSomething is called, it will always call the most derived override. So when we create an instance of our child, we'll call the parent constructor first. It will call doSomething. DoSomething will expect message to be assigned, but it hasn't been. So for that reason, you want to avoid calling virtual methods within a Constructor. Even if you do it correctly, if someone then inherits from your own class, and then they override a virtual method to expect values from the Constructor, you're potentially going to confuse the heck out of them, because it's all going to break. So throwing exceptions. I'm of the opinion that how you fail is almost as important as how you succeed with an API. Users tend to learn not by reading documentation. They tend to learn just by grabbing some code and start exploring classes and instantiating them and calling methods until stuff works. And giving them helpful exceptions helps them learn by failing. So in my JSON.NET library, probably the most common error that people encounter is deserializing incorrect JSON onto types. So in this case, we've got a person class that has a string name and hobbies, which is a list of strings. But in our JSON, hobbies is just a string. It's common delimited, but if you try and deserialize a string into a list collection, it's going to fail. And the error that people got. So this was back in JSON.NET 1.0 many years ago. This is the error that people would get if they tried to do that. So expected JSON array contract got JSON string contract. So internally within JSON.NET, I was expecting a string, but I was getting an array. But I was giving the users a very bad message. And even though I was throwing an error, which is great, the worst thing you can do is just silently fail, it wasn't helping a user. A user would see this, so it would get confused. They would ask for help. They would have to read documentation. They would potentially just throw JSON.NET away and they'd use something else. So this is an example of a good error message. Later I improved the error message to be something more like this. So error converting value, I just got the string value. To type, and I'd list the type, and then I'd throw that as an error. It's immediately much more obvious what's going wrong. They would look at that hobby's value. They would potentially see, hey, that's a string. They would look at the type that they'd be deserializing to. Hey, that's a list, it's not a string. That's why I'm failing. And the user's able to quickly fix the mistake themselves without having to go looking for help. To go even further, in later versions of JSON.NET, I included information like the position of the JSON and the path to it. So now it's immediately obvious, even if it was a huge JSON file, exactly which JSON was causing the error. And a user would be quickly able to fix this issue. And if we compare it to what they were originally getting, it's much easier for a user to understand what's going on and what went wrong and fix it themselves. So with errors, it's very important to fail fast. So imagine we had this report service, and it took some credentials. In this case, we're passing it null. But because we're not validating it, down here, if we then try and call generate report, and we do give it a valid argument, we're getting a null reference error. But we're getting a null reference error from code earlier than where we got the error. So the developer is really confused. What you want to do is you want to fail as soon as the user does something wrong with your code. That makes it immediately obvious to them what's wrong, where it went wrong, and how they can fix it. So with exceptions, you want a subclass exception to provide your own custom exceptions. This allows users to catch exceptions that are specific to your library and ignore exceptions from potentially their own code. So in this case, I've created my own JSON serialization exception. I inherit from exception. I've got a constructor call, which then passes value to the basic exception. This will then allow users to do try catch, and they only catch a JSON exception. Then when you're performing operations, quite often it's useful to catch exceptions from the underlying.NET framework and wrap it in your own exception and then re-throw that to the user. So in this case, I've got a property info, which is used in reflection, then got a value, which has been set on a target. If there's an error inside that, perhaps the value doesn't match the property type. When an error happens, I'm catching that exception. I'm adding some additional information to it. So in this case, I'm giving the name of the property, which calls the error. And then I'm re-throwing that. It's very important when you do this, when you re-throw an exception, that you wrap it. So in this case, I'm passing it to the constructor of my own exception. This preserves the stack trace. Otherwise, whenever you throw a new exception, you throw away the stack trace. So in this case, the original exception will become an error exception. So when designing for extensibility, you want to use virtual methods with care. So there's two schools of thought with virtual exceptions. There's one, which is make everything public, make everything protected, nothing's private, everything's virtual. As a user can do exactly what they want, they can override all the things. And that way, your library is infinitely powerful. The problem with that is it's quite easy to break existing code with virtual methods. You already saw in that previous case with the constructor of virtual method in there, can cause issues. So I'm of the opinion you want to use virtual methods with care. They're powerful, but they're dangerous. And you need to put thought into how they're used. So the other thing you want to think about when designing for extensibility is prefer composition over inheritance. So inheritance is very useful. But composition is potentially much more powerful and provides much more ability for users to customize how something works. So the case of JSON.net, the JSON sterilizer, there are zero virtual methods on it. All the extensibility to it is provided through other objects that you can plug into it. So you can plug in a reference resolver. You can plug in a contract resolver. You can plug in a trace write. You can plug in your own custom JSON converters. By doing that, you're also encouraging reusability. People can implement their own reference resolvers, contract resolvers, JSON converters. And then they can publish those to the web. And then other people can use those and plug those in within their own applications. So the final thing we'll look at is designing for performance. So a lot of the key things for designing performance have actually already covered. So lazy constructors. So you want to have your constructors just to initialization. You want to lazily defer work until it's needed. Cheap properties. So property should be fast. You don't want to use exceptions for flow control. Throwing exceptions is very slow if you're doing a lot of them. So perhaps if you've got a web request and you only throw one exception, that's fine. If you're doing a web request and you've got a for each loop and within each iteration you're throwing an exception and that loop runs a thousand times. Those a thousand of exceptions can certainly add up. So avoid using exceptions for flow control. Use exceptions just for when something actually does go wrong. Use structs when appropriate. If you're allocating tens of thousands of objects, that can be fine. But doing it within a high throughput web application, you can create a lot of garbage collection which can potentially slow your website right down when garbage collection does happen. You want to use async properly. I'm not going to cover how to use it properly because that's literally an hour in itself. So that's the whole async await that's been introduced from a newest version of.NET. Doing it properly is very hard. I recommend if you do have an API that does have long running operations, look into how to use it properly. And I think it's very important when designing for performance to avoid harming API usability for internal performance gains. So computers tend to get faster but your API is not going to get more usable over time. So even if it's slow today you might figure out a way to make it faster and future internally. But once you've published an API and people are using that API, you've got no way to really take it back. So some more information. If you're curious about API design and you want to know more, I really recommend this book. It was written by Brad Abrams. He turned that phrase the power of sameness and some other people at Microsoft. The most recent version of this, the framework design guidelines, is a second edition. It came out in 2008. So although that was a little while ago, the vast majority of it is still applicable today. And I really recommend it. And another great resource is this YouTube video. It was put up by a guy at Google. How to design a good API and why it matters. And although Google, they're more C++ and Java and Python, none of it is.NET specific. A lot of the high level concepts are still applicable and it's quite a good watch. So that's everything I have for you today. It looks like we're bang out of time. I'm going to hang around to answer questions. But other than that, you've been a great audience. And I hope everyone has learned something. And thank you very much. Thank you.....
 Hello.  Are we good?  Can anyone hear me?  Awesome.  OK, so we'll get started.  So hello, everyone, and welcome to the session.  It's wonderful.donate API design.  So we'll get started with some introductions.  So my name is James Huydon-King.  I'm from Wellington, New Zealand, all the way down there.  And I've been a Donate developer for a little over 10 years.  If you're familiar with Flight of the Concords,  they have some wonderful demotivational photos about  posters about New Zealand.  It's a lot further, having just flown on a couple of days  ago.  So probably what I'm best known for, about eight years ago,  I started a project called JSON.NET.  And from that project, I've gained, and just  from regular Donate development, I've gained quite a bit  of knowledge about API design.  And I think it's a little known skill that's  talked about amongst Donate developers.  There's been a lot of focus on REST API design.  I think it would be good to focus a bit on Donate API  design.  So to get started first, what is Donate API design?  What is a Donate API?  So really an API is types, it's properties, it's methods.  So it's the members almost types, it's constructors, it's  perhaps more Donate specific constructs like events.  It's really the code that you interact with when working  with a library.  And API design is really about communicating what an API  does.  If you could stand over the shoulder of every single  developer who was using your code, you wouldn't need to  worry about API design because you could just tell them.  But because you're not there, you need to create APIs that  are able to communicate to users.  Yes, so communicating to developers.  So imagine, so we'll give a little example.  Imagine we've got some code here.  We're connecting to a database.  We're getting a count from a database table, and then we're  returning that.  The problem with this code is we're creating a connection to  a SQL database, but we're not closing it.  The way as an API designer, you communicate to a user that  there is a resource that they need to clean up is you make  it implement iDisposable.  As soon as you implement iDisposable, that developer  should be able to see that this is something that they need  to clean up.  And if they don't already know that, then hopefully either  Visual Studio or a tool like Resharpid does tell them.  And when they see that they need to clean that code up,  they'll just change their usage of the API.  So in this case, it's the SQL database API, and close  their connections and fix their code.  So it's all about creating code which communicates to  developers how they should use it.  So why is API design important?  So it's potentially the difference between an API  that discourages users, waste their time through them going  through trial and error, having to look at documentation,  and a good API which is creating productive and  happy users.  API design is also important because APIs are forever.  So ideally, any API, so any code which is designed to be  reusable, shouldn't change.  So I've got a little star against APIs are forever,  because there's sort of like a range of how much change you're  able to do to an API.  If an API is for internal use only, so really you're just  referencing another project, and perhaps it's a reusable  data layer to talk to your database, then it's pretty  easy to change.  If you rename something, and there are perhaps a method,  then Resharpher or Visual Studio will automatically rename it  throughout Visual Studio, throughout the rest of your  solution.  If you're shipping a DLL within your company, that's  perhaps slightly more problematic when making changes.  If you're publishing a framework on Nougat, that's  harder still, because you aren't able to immediately  communicate to your users that the API is broken.  The worst case scenario is if you're publishing a Nougat  package, and then that Nougat package is dependent upon  other Nougat packages, you make a change which breaks other  Nougat packages.  Anyone who uses those Nougat packages is broken until  those other library authors go and update their own packages.  So the worst case scenario happens to be my own  library, json.net.  So this was created by a developer, a program manager,  on the Nougat team.  And at the bottom of an inverted stack of cards is  json.net.  If I make a breaking change, then I could potentially  break hundreds, maybe even thousands, of other Nougat  libraries.  1,500 other Nougat libraries depend upon json.net.  So when you get to that sort of scale, APIs really are  forever.  And you make a breaking change to a low-lying library like  json.net or the.NET framework, you're going to  create a lot of unhappy developers.  And the thing about APIs is every piece of code that  uses that API in its current form is an investment in it.  If you're breaking APIs, you're destroying that  investment in that API.  API design is important because everyone really is an  API designer.  Code should not just be maintainable.  Ideally, it should be reusable.  So you want to aim for dry.  Don't repeat yourself.  So really, when you're designing APIs, this might be  your payment service within your own solution.  These are some.NET classes, methods, properties.  This is an API.  You want to think about reusability.  So thinking about API design encourages good programming.  So what makes a good API?  A good API should be both easy to learn and easy to use.  So easy to learn.  It should be consistent with the platform.  If you're working in the.NET environment, if you're  publishing a.NET package, you should follow the.NET  naming standards.  You should use.NET constructs.  Like if you're communicating with the file system, you  should talk to streams.  You shouldn't invent your own way to talk to the file  system.  A good API should be consistent with itself.  If you're doing two tasks and two separate places, you  should do those two tasks the same way.  You shouldn't unnecessarily complicate and confuse things  for your users.  And a good API should be easy to use.  So it should be well-named.  You want to aim to make it as strongly typed as possible.  Ideas are fantastic.  Visual Studio, amongst Tony developers, is fairly  ubiquitous.  IntelliSense is awesome.  So strong naming is strongly typed classes are your  friends, it helps with IntelliSense.  So with the easy to use, you also conversely want it to  be hard to misuse.  So for example, if a user does something wrong and they do  a set something to a bad value, you want to validate that  and throw an error quickly and tell them that they've done  something wrong.  So perhaps an example of some bad classes, a bad API with  them in the.NET framework, is this code.  So just immediately looking at it is not following the .NET naming standards.  Imagine if you will that these were constants instead of  enumeration.  So enum provides a great strongly typed way of telling a  user what values are available.  So you'll get a compile error otherwise.  This code is invented its own way to talk to a file system.  It's using its own custom file adapter rather than just  taking the built-in.NET stream.  And it's using setters instead of properties.  So it's not using the built-in.NET, well, in this case,  C-sharp language features.  So this might be an example of a Java API that someone's  ported directly to.NET without putting in the time and  effort to make it easy to use within the.NET environment.  And I don't know about you, but if I came across having to  use this sort of library, I'd be very upset.  It's not pleasant code to use.  If anyone's ever used a Java port to.NET, it's not a  pleasant experience.  So a good API should also encourage code that uses it to  be easy to understand and maintain.  So an example I can think of that is imagine this is an  in-hybernate mapping class, or mapping  configuration XML file.  So in-hybernate is a.NET ORM.  This piece of XML is mapping a.NET type to a database  table, and that's what it does.  The problem with encouraging code like this, in this case,  XML, is it's verbose.  You're having to go in.  You're manually typing it, and it's brittle.  It's not strongly typed.  If you rename your.NET class, then this is going to break  until you run.  If you compare that to something like using just plain  attributes, this.NET class with attributes, it's reusing  the property names rather than having to specify them  manually like you were in the XML.  By placing a property on an attribute on a property, you're  going to immediately use both that property name.  You can use that type, likewise with the ID.  So this sort of pattern is like convention over  configuration, and it's sort of leveraging the built-in type  that you're already using rather than having to duplicate  all the mapping information in a XML file.  And it's leading to code which is both easy to use and  understand and maintain.  You want to create APIs that are sufficiently powerful to  meet requirements, but not overly powerful.  So when designing APIs, there's often a conflict between two  separate worlds, there's creating both API that is  powerful enough to meet the needs of a broad range of  developers, but is still simple for users who just need a  small subset of it.  So when you're designing an API, you just need to be careful  that you don't ruin simplicity by being overly powerful.  A good API can also evolve.  So bugs can be fixed, features can be added without  making breaking changes.  So a good example of that is the.NET framework.  So it's maintained compatibility pretty well over  the years, while still being able to add lots of new features.  So now we'll talk about a bunch of general API design  principles.  And perhaps the most important principle is the pit of  success.  So this is a term that was coined by an employee at  Microsoft.  So the pit of success.  In stark contrast to a summit, a peak, or a journey  across a desert to find victory through many trials and  surprises, we want our customers to simply fall into  winning practices by using our platforms and frameworks.  To the extent that we make it easy to get into trouble, we  fail.  So success shouldn't be climbing a mountain.  Users shouldn't need to figure out how to make complex  configuration files or understand complex processes.  It shouldn't be like trekking across a desert.  You shouldn't need to write tons of boilerplate code to  successfully do a task with an API.  You shouldn't have to wade through tons of documentation,  tons of methods and settings on many different classes to  find what you want.  Success should be as simple as falling into a pit.  So the goal when you're designing APIs is to make it  easy to succeed and hard to fail.  And hopefully we'll look at a whole bunch of ways of doing  that throughout the rest of our presentation.  Another general principle is the wall of complexity.  So the wall of complexity is the idea that your API should  offer a steadily increasing slope of difficulty as their  usage becomes more complex.  So if your user is suddenly requiring a huge increase in  knowledge or a huge increase in efforts to perform an  additional minor task, that's an example, perhaps, of them  running into a wall of complexity.  So imagine you have an amazing form and suddenly you need to  do a specific bit of custom validation and what you  expected to take 30 minutes takes two days.  That's an example of you hitting a wall of complexity.  And chances are when a user hits a wall of complexity,  they're going to fail.  And they're not going to have a  pleasant experience.  It's great, isn't it?  So an example of a framework that I think hits a wall of  complexity is the good old ASP.net web forms.  So web forms was advertised as a way of creating rich web  pages on the server using simple drag and drop into an IDE,  double click on a button, and suddenly you've got an event  and everything's nice and simple.  The problem with web forms is if you need to suddenly start  performing even moderately complex tasks, if you need to  perform even moderately complex tasks, you suddenly hit this  enormous wall of complexity.  Of all this knowledge, you suddenly need to understand  about the ASP.net lifecycle and the web form page lifecycle,  all the events that happened.  So this is like a diagram showing all the different  events that can be raised off a web form's web page.  So you need to know when the post-back happened, when  data binding happened, when rendering happened.  So for me, I always hit this problem when suddenly you  needed to post-back values to data bounds, drop downs, and a  repeating list.  And suddenly you need to worry about what's going to  happen, and suddenly you need to worry about what order you  bound the list, what order the post-back values were applied  to this list.  It all became very complex.  And all from a framework which is advertised as something  which is meant to be just drag and drop and double click  and you're done.  So a framework which did it better, in my opinion, is the  MVC.  So obviously MVC, it requires you to have some knowledge of  HTML and have some knowledge about HTTP.  But it's really a steadily sloping increase of difficulty  as you do more and more complex tasks.  If you need to suddenly do complex Ajax callbacks and you  have complex JavaScript, well, that isn't suddenly orders  of magnitude more difficult than what you're currently  doing.  MVC provides nice hooks for you to add in complexity, but you  only need to hook them in when needed.  An example of a framework which does this wall of  complexity really badly, and it's almost an anti-pattern, is  WCF.  So WCF puts all the complexity up front, even if  you're doing a very simple task, like you want to have a  basic HTTP service and you want to give it some XML and get  some XML back.  There's all this configuration.  There's all this knowledge, all this learning that you need  to understand, especially the configuration.  I could never get it right.  And you need to all understand that all up front.  And it's not a great framework.  So the next general principle is the power of sameness, which  sounds kind of weird.  It's a term coined by a guy called Brad Abrams.  And he's a ex-Microsoft employee.  And the idea of the power of sameness is by creating APIs  that use features that developers already know,  developers can quickly achieve tasks because they already  know how to do it.  An example, and this is the example that he uses, is that  of interacting with the car.  No matter what car you're working with, well, you're in,  whether it's a taxi, it's your friend's car, it's your own  car, it's a car you're renting, door locks tend to work  the same way.  If you're confronted with a door and you need to unlock it,  chances are you don't need to ask for help.  You don't need to read an instruction manual because they  tend to work all exactly the same way.  And that's the power of sameness, likewise with a  seatbelt.  All seatbelts tend to work the same way.  So if we imagine that within the context of a.NET API, you  want to use naming standards that everyone's familiar with.  You want to use common types and interfaces like I  dispose of at everyone's familiar with stream.  You want to use configuration patterns that people are  familiar with.  So you want to use web config, app config, to put  configuration rather than your own custom files.  By using these techniques that developers already know  about, you're helping them fall into a pit of success.  They already know how to do these things, so they don't  need to learn them again just for your own API.  So when you're starting out designing an API, probably one  of the most important things is you want to start small.  You want to start small because you want to firstly  provide a solid foundation, but also because you want to  release quickly.  You want to release quickly because at least initially  you're just guessing how your API is going to be used.  You don't know exactly all the different ways developers  could potentially use your API.  So the sooner you release, the sooner you can start  getting feedback.  And by starting small, you're minimizing potentially the  amount of changes that you need to make.  So if you've already made mistakes, the number is smaller.  What you want to think about with this is incremental  improvement is better than delayed perfection.  And that's especially important because your idea of  perfection could be quite different than what your  user's idea is.  You want to listen to user feedback.  But when listening to user feedback, you need to be able  to decipher what users say versus what they mean.  So users will tend to suggest for features, specific  features that solve their problem and perhaps don't  address other people's problems.  So imagine if you will, you had a custom list class.  It has some strings in it.  And you had a method to sort.  A user of your API will tend to come along and suggest, what  you need is a new method that sorts in exactly this way  that I want it to sort.  And what you could do is you could add a new method on.  Crazy user sort.  It implements a sort for them.  And that's what they've suggested.  But while that works for them, it doesn't work for other  developers.  So you would need to, each new developer who uses your API  might come along and request a new sort mechanism.  That's bad, both because it's putting lots of work on you.  And it's bad for your users because they're waiting for  you to add new sorting methods.  So you don't want to do that.  What you really want to listen to is what they mean.  What they mean is they want a way to be able to customize  the sort, and they want a way to be able to do it themselves.  So this is an example from the.NET list class.  And it has a sort function on it that takes a comparable  delegate.  The delegate takes two values.  And then within it, you can hook in your own custom  comparison logic and then sort it yourself.  And by doing this, you've created a mechanism that works  not just for the developer who said they needed a way to do  custom sorting.  It works for all users of your API.  So as well as positive feedback, you can also get  negative feedback.  And just because it's negative feedback, it doesn't mean you  don't want to listen to it.  So there's this quote from Benjamin Franklin.  Critics are our friends.  They show us our faults.  So it might be a user complaining on Twitter about  how horrible something is.  But you want to think about what they say and think, is there  a way I can solve their problem for them?  So expect to make mistakes, especially at the start.  So your initial release, you're really just  guessing what users want and how they'll use your API.  So it's quite easy for you to make mistakes.  And you should pretty much expect to do so.  So the way you can get around this is starting small and  releasing often.  So that both minimizes the amount of changes that you'll  make, so the mistakes that you've made, they've been  minimized.  And that whole releasing early and often incremental  improvement.  If you do make a mistake, don't be afraid to make types  and members obsolete.  So to do that, within the.NET framework, you place an  obsolete attribute on a member that will show up in  tele-sense.  It will be crossed out.  So all new users won't use it.  And any existing users of your API, when they recompile,  they'll get a compiler warning.  And within that attribute, you can provide a description of  what they should do instead.  Not all feature suggestions are good.  And also not all pull requests, if you've got your source  code on something like Git, is good.  Don't be afraid to say no if you don't think it's a good  feature.  With features, you want to think about quality over  quantity.  You want to focus on doing a good job for the most users  possible.  And if you can help those perhaps non-normal use cases  without hurting your core users, then that's great.  Perhaps accept those pull requests.  But otherwise, don't be afraid to say no if you don't think  it's appropriate for most users.  So those are the general principles of API design.  So the rest of the presentation, we're going to focus on  lower level API design and how it relates  specifically to.NET.  So the.NET framework has extensive naming guidelines.  And for the most part, unless you've got a very good reason  otherwise, you should always follow them.  So the first one is always Pascal case, namespaces,  types, and delegates.  So Pascal case, as you can see on that slide, each word  should start with a capital letter.  You also want a Pascal case, methods, properties, fields,  and events.  And you want a camel case parameters.  So the.NET naming guidelines are pretty simple.  Pascal case, everything except parameters to methods or  constructors, and camel case those.  You'll note in this code, I have a private field and it's  starting with an underscore.  The naming guidelines are really just for public  members and public types.  Anything private or internal, users won't see anyone who's  interacting with your API won't see.  So you can name those however you want.  I've always done an underscore on my private fields.  But yeah, whatever you want.  One interesting rule that a lot of people don't follow is  you want to always Pascal case acronyms that are three  letters and longer.  So some examples.  In the.NET framework, it is an XML document with XML all  uppercase.  It's XML document with XML Pascal case.  Likewise, HGB client.  But then if it's only two letters, so in this case, IO  exception, you can leave those both as capitals.  Some additional tips when naming your types of members.  You want to avoid acronyms.  So a good way to test whether an acronym is acceptable is just  go to Google.  And if lots of people are referring it to it by the  acronym, so if people are talking about HTML rather than  Hypertext markup language, then the acronym is great.  Avoid abbreviations.  Well, I'd say even stronger.  Don't abbreviate.  So IDEs these days.  So Visual SEO, you have auto complete.  Typing, writing code, that's fast.  You write code once.  You read it dozens of times.  So you want to make your API optimized for readability  rather than quickly writing it within reason.  So that will help avoid developer confusion when  reading your APIs.  So a bunch of other random tips.  So interfaces, start those with deny.  Generic type parameters, start those with a T. So in the  case of dictionary, a generic dictionary, it takes T key and  T value as its generic types.  And then there's a bunch of.NET types that when you  inherit from them, you should always suffix with a certain  bit of text.  So attributes should always end with attributes.  If you're implementing your own custom exception class, it  should always end with exception, stream with  stream, and so on.  So interface and abstract base class design is interesting.  So there's a bunch of common pitfalls that people make when  implementing interfaces and abstract base classes while  designing them.  So the first one is they put too many methods on an  interface or an abstract base class.  So the canonical example, the one that I always think of, is  the old membership provider in ASP.NET.  So all these types, and all these properties, are  declared as abstract on this base class.  And whenever you implement it, you need to  implement all of them.  So quite often, I've needed to implement this to plug it  into some other application.  And all I needed to do is to do validation.  And all I end up implementing is if you can read it  closely, there's a validate user there and a get user.  So those were the only ones that the other framework was  using.  But because this base class had all these abstract members on  it, I had all these additional methods.  And I just had to leave them as not implemented exceptions,  throwing not implemented exceptions.  So if you're familiar with SOLID, this is an example of  the interface segregation principle.  So you want to keep your interfaces small and focused,  and likewise with your base classes.  So the other common pitfall is having a method that is  impossibly complex to implement.  So a good example of this with the MedotNet framework is  Iquariable.  Iquariable takes has just a couple of methods on it that  you need to implement.  But one of them takes an expression tree.  An expression tree can be an expression tree of any  expression.  And really, Iquariable needs to be able to handle any  expression given to it.  But really, there's actually only one proper  implementation of a link provider.  And that's link over in memory data structures.  Every other link provider, like NT Frameworks link  provider, if you give it a certain expression, it's  going to fail.  So I'm not saying in this case Iquariable was bad for this  specific case, but it's something you want to keep in  mind.  Have you got a method on your interface or abstract base  class that is just impossible for the average  person to properly implement?  So also with abstract base class design and interfaces, you  want to provide an implementation, and you want  to provide consumers of this implementation.  By doing this, you're ensuring that you've thought  about how your interfaces or base classes should be used.  So an example I can think of in the.NET framework of where  this wasn't done is Iquariable.  So Iquariable shipped in.NET 1.  And some classes implemented Iquariable, but no APIs  actually consumed Iquariable.  And unfortunately, the Iquariable description of how  it should work is a bit ambiguous.  Like should Iquariable clone just the current object?  And not as child object?  Should it clone all its child objects?  Do all its child objects then need to implement Iquariable  before they can be cloned?  And because it wasn't properly defined how it should work,  and because no one actually used it in the.NET framework  v1, it's sort of become this orphaned interface that's  never been used.  And because it's already in there, it can't really be  reintroduced now and done properly because it's been  taken up.  So this would be a case of something which perhaps should  have been left out, and then added if needed at a later date.  And because it's never used, it's forever alone.  So structs are interesting.  So structs are similar to classes.  You can do a lot of the same things you can with classes.  The difference between structs and classes is that structs  aren't allocated on the heap.  They're value objects.  They're on the stack.  And because of that, there's no need to allocate them or  garbage-click them.  So they have some potential performance benefits.  But there's only a certain number of circumstances when  you want to use a struct.  Because they behave subtly different to classes, and  users generally expect something to work like a class, you  want to use it only when performance is important.  They represent, the struct will represent a single value.  The struct is small.  So the difference between a struct and a class reference  when you're passing around is a class reference.  So as reference to a class that's sitting on the heap is  the reference will always be the exact same size no matter  how big the class is.  The difference with a struct is because when you're  passing around and assigning it to variables, you're passing  around the entire struct.  If your struct has hundreds and hundreds of fields on it, and  it's potentially quite large, you're going to use up a lot  of memory each time you create a new one, or you pass it to  a method.  So for those reasons, you want to only use a struct when  you have a small number of fields.  So the rule of thumb that the Microsoft guidelines  recommend is under 16 bytes.  So if the number of bytes of your field, so if you've got  ints and floats on there, if they are greater than 16 bytes  and you probably want to stick with the class, you also  always want your structs to be immutable.  You can get some really odd behavior because they're  stack allocated when they get boxed.  So if you assign it to an object reference, that.NET  framework will box it.  And if you then make modifications to that box  struct, it won't flow through to other places.  It's as complex the situations where it can happen.  And for that reason, you should really only use structs  which are immutable.  Struct should also only have a valid empty state.  So because they're stack allocated, the default value  isn't null.  The default value of a struct is a struct with all its  fields with a default value.  So if you, for example, create an array of structs, each of  the elements in that array won't be a null value.  It will be an empty struct.  So it'll be a struct with its default value.  So for example, the datetime in.NET, its default state is  0, 0, 0, 0, 0, 0.  And decimal, which is another example of a struct  within.NET, its default value is 0.  So you need to think about having a valid empty state.  And finally, a struct should implement iequitable.  Because structs aren't reference objects, when .NET compares the two of them, it isn't as simple as  comparing two references and seeing whether they point  towards the same object.  What.NET does is it will use reflection to reflect over  all the structs' fields and compare them one by one, which  is quite slow.  So you want to manually implement iequitable yourself.  So this is just a quick example of a struct done well.  So thanks for notice.  The fields are immutable.  So we've got a constructor, which is assigning those fields.  And also down there, we've implemented our own equitable.  So equitable is quite simple.  It's just an equals method, which takes the same type as  itself.  And then within there, you can manually do your comparisons.  So structs are great for performance, but you just  want to be careful about how you use them.  So designing enums.  Enums are great for closed sets of choices.  It allows you to strongly type a choice.  And by strongly typing it, you're giving users  IntelliSense, you're giving them documentation.  So a great example of a struct, I mean a struct, an enum, is  Day of Week.  It's small, it's constrained, it's not going to grow.  A bad example might be Windows version.  Microsoft's constantly releasing new versions of  Windows, it's constantly releasing new service packs.  Every time you release a new version of your framework, you  just going to have to add more and more Windows versions.  This might be a case where a better choice might be using  integers represent a version.  With enums, you want to provide a value for zero.  Again, they're value types.  The default value of enum is zero.  And you just want to provide a named value for that.  So in the case of string split options, this is an enum  with a.NET framework.  Its default value is none.  The first enum value in this case is always zero.  Then the next one will be one.  Unless you provide numbers yourself, it will always start  at zero.  So an enum can support having multiple values at once.  And the way you do this is by specifying the flags  attribute on that enum.  So this is an example from JSON.NET of a flags enum.  It's got the flags attribute on it.  And then what you need to do for each value within the  enum, and unfortunately there aren't more of them on this.  And otherwise you'd see a cleaner is you should always go  by powers of two.  So you should always start with zero, then one, then two,  then four, then eight, then 16, and 32.  By doing that, you are able to then give users the option  to and those options together.  So that way a user can say a value should enable  reserve reference handling both for objects and arrays by  anding those two enums together.  And in this example, within a flags enum, you can do that  yourself.  So all, for example, is an example of objects and arrays  being added together.  Well, in this case, odd.  So with methods, you want to provide descriptive  parameter names.  Not only do they appear in an IntelliSense, in the latest  version of C-Sharp, you can also have named them as  named arguments.  So by giving descriptive parameter names, it can be  the difference between a user quickly and easily using a  method and succeeding or having to ask for help, because  they don't understand how it should be used.  So this is an example of just helping them fall into a pit  of success.  With methods, you want to have a consistent parameter  overload order.  So you don't want to confuse developers by mixing around  the orders, the order of arguments, the parameters  that the method overloads takes of arguments.  So an example, this isn't a terribly good example, because  this is actually constructors.  But this is from within the Donet framework.  It's an example of mixing up the order of the same  parameters, but just in different orders.  So the one down the bottom, pretty much every other  exception in.NET will always take message as the first  argument.  But argument null exception is the one exception in the  entire.NET framework.  It takes a pram name first.  And quite often, you see developers getting them wrong  order.  And then the description when argument null exception is  thrown is a little weird, because it gives the message  as the parameter that's null and then the parameter name  as the message.  When you're designing methods, you want to prefer enum  over boolean parameters.  So an enum parameter with a descriptive name is much more  obvious in what it does than a boolean parameter.  So an example, we've got two overloads here.  We've got an equals, which takes two strings and a boolean  and equals, which takes two strings and an enum.  So in that first overload, it isn't immediately obvious  what that true is doing.  Is that true to ignore case?  Is that true to ignore culture?  Is that true to trim whitespace from the beginning and  the end of the string that we're passing in?  It's not immediately obvious.  Well, with the second overload, the one which takes the  enum, straight away a user can immediately understand what  exactly that's doing.  So that's why you want to just prefer enums over booleans  for parameters when you can.  And even if you just have two.  So even if you could use true false, it's a lot easier if  you just define an enum.  You want to avoid out and ref parameters.  So this example, when someone wants to call this method, so  they're passing in an assembly path and they're getting out  a title, they're getting out a description, and they're  getting out a company for that assembly.  They need to define all these arguments before they can call  your method, and then they pass them in.  Much easier for a user to just use a method which returns  one type.  So just create your own object, assign the values to it,  and return that.  And it's much easier for users to use.  Don't be afraid to create helper methods.  So a goal of the pit of success is to prevent users  from making mistakes.  So anytime you have boilerplate code that's repeated over  and over within your application, whenever someone  potentially needs to use an API, think about wrapping that up  in a helper method.  So by wrapping, having to create a string reader and then  creating a JSON text reader which uses a string reader,  then having a schema resolver and a schema builder, it's  much easier.  Really, all the user is passing in as a string, and  they're expecting to get back this JSON schema object.  So by creating a helper method, we've eliminated the need  for a user to firstly know to create this boilerplate code  to potentially make mistakes in it.  And we're helping them fall into that pit of success.  So properties are quite interesting.  So although internally, properties are really just  methods, users expect properties to act like fields.  And you should strive when possible to meet what users  expectations.  So the first thing users expect about properties is they  should be fast.  So imagine we've got this DB context object, and we've got  a products property on it.  And each time you call dot products, it's going off to the  database and loading all the products out of the database.  And then imagine the users put it in a loop, and there's 100  products.  They're going to load every single product from a  database 100 times.  Now a user probably wouldn't expect that from a property.  They'd expect it to be fast and instant and have very little  or no time or overhead.  They'd probably certainly wouldn't expect it to call  off to a database.  So imagine you changed that to a method.  So immediately, this looks a bit more suspect.  If you saw code which was doing this, you would think  about, am I doing that the right way?  And methods convey the expectation that there's  potentially work is going to go on inside this method.  The method might be slow.  So you probably want to case your result once and then use  that.  So by not using a property in that case, by using a method  instead, you're encouraging users to use the code more  correctly.  Also with properties, the result should be consistent.  So you don't expect fields to suddenly change.  Properties probably shouldn't change either.  So imagine we had this a Goode object and on it we had  new Goode.  So new Goode generated a new Goode.  That's probably not quite correct.  What's probably a better way to do it is have it as a method.  Just like you can't have set only fields, you probably  shouldn't have set only properties, even though  Donet allows you to do it.  So imagine we had a user class and we had a password  property on it, but it was set only.  And when we set that password property internally, we would  hash it and we'd assign that to a field.  That's a little weird to use.  When they see that there's a password property on a user,  they'll probably expect they both be able to assign to it  and get a value from it.  So in this case, if you don't want to use it to be able to  access the result, just change it to a set only property.  And users would be much less confused.  So for constructor design, constructors should be lazy.  Where possible, you want to defer work until it is needed.  So imagine in this case, we've got an XML file object.  And it's got a constructor on it, which takes a path.  And then within the constructor, we're going off to the file  system, we're loading that file into an X document, and  we're assigning it.  And then when someone calls getXML, then we actually  return that X document.  Imagine then that someone had this little link statement.  So they were getting all the XML files on the C drive that  ended with XML.  They loaded them in.  They instantiated these XML files.  And then they signed that to a list.  Imagine further that a user then only uses maybe one or two  of those XML file objects.  Even though they've only used one or two, you've still gone  off to the disk and loaded hundreds of files potentially.  So what you want to do instead is make it lazy.  So you want to defer the work only until it's needed.  And constructors should really just be about initializing  private fields from parameters.  So in this case, we're now just assigning path to its own  string.  And then within getXML, at that point we do the work.  And because we probably still want getXML to be fast, we  cache the XML document.  So we now get the best of both worlds.  We still get our own custom XML file class, which has got  our business logic.  But we're deferring the work until it's needed.  With Constructor Design, this one isn't terribly important.  But all you're doing is you're setting a field from a  parameter.  Just make the property name match the same name as the  parameter.  It just helps users understand what's going on more  readily.  So one interesting thing about Constructors, and this is  something a lot of people don't know, is you want to avoid  calling virtual members within a Constructor.  So imagine we have this parent class.  And it's got a Constructor, which  calls doSomething.  DoSomething is virtual.  We then create a child class that inherits from parent.  Within its Constructor, we assign a message.  And then in doSomething, we use that message field.  Now there's a problem here.  The problem is the order of which Constructors are called.  The parent constructor is called before the child  constructor.  But when doSomething is called, it will always call the  most derived override.  So when we create an instance of our child, we'll call the  parent constructor first.  It will call doSomething.  DoSomething will expect message to be assigned, but it  hasn't been.  So for that reason, you want to avoid calling virtual  methods within a Constructor.  Even if you do it correctly, if someone then inherits from  your own class, and then they override a virtual method to  expect values from the Constructor, you're potentially  going to confuse the heck out of them, because it's all  going to break.  So throwing exceptions.  I'm of the opinion that how you fail is almost as important  as how you succeed with an API.  Users tend to learn not by reading documentation.  They tend to learn just by grabbing some code and start  exploring classes and instantiating them and calling  methods until stuff works.  And giving them helpful exceptions helps them learn  by failing.  So in my JSON.NET library, probably the most common  error that people encounter is deserializing incorrect JSON  onto types.  So in this case, we've got a person class that has a  string name and hobbies, which is a list of strings.  But in our JSON, hobbies is just a string.  It's common delimited, but if you try and deserialize a  string into a list collection, it's going to fail.  And the error that people got.  So this was back in JSON.NET 1.0 many years ago.  This is the error that people would get if they tried to do  that.  So expected JSON array contract got JSON string contract.  So internally within JSON.NET, I was expecting a string,  but I was getting an array.  But I was giving the users a very bad message.  And even though I was throwing an error, which is great, the  worst thing you can do is just silently fail, it wasn't  helping a user.  A user would see this, so it would get confused.  They would ask for help.  They would have to read documentation.  They would potentially just throw JSON.NET away and  they'd use something else.  So this is an example of a good error message.  Later I improved the error message to be something more  like this.  So error converting value, I just got the string value.  To type, and I'd list the type, and then I'd throw that as  an error.  It's immediately much more obvious what's going wrong.  They would look at that hobby's value.  They would potentially see, hey, that's a string.  They would look at the type that they'd be deserializing to.  Hey, that's a list, it's not a string.  That's why I'm failing.  And the user's able to quickly fix the mistake themselves  without having to go looking for help.  To go even further, in later versions of JSON.NET, I  included information like the position of the JSON and the  path to it.  So now it's immediately obvious, even if it was a huge  JSON file, exactly which JSON was causing the error.  And a user would be quickly able to fix this issue.  And if we compare it to what they were originally getting,  it's much easier for a user to understand what's going on and  what went wrong and fix it themselves.  So with errors, it's very important to fail fast.  So imagine we had this report service, and it took some  credentials.  In this case, we're passing it null.  But because we're not validating it, down here, if we  then try and call generate report, and we do give it a  valid argument, we're getting a null reference error.  But we're getting a null reference error from code  earlier than where we got the error.  So the developer is really confused.  What you want to do is you want to fail as soon as the user  does something wrong with your code.  That makes it immediately obvious to them what's wrong,  where it went wrong, and how they can fix it.  So with exceptions, you want a subclass exception to provide  your own custom exceptions.  This allows users to catch exceptions that are specific  to your library and ignore exceptions from potentially  their own code.  So in this case, I've created my own JSON serialization  exception.  I inherit from exception.  I've got a constructor call, which then passes value to the  basic exception.  This will then allow users to do try catch, and they only  catch a JSON exception.  Then when you're performing operations, quite often it's  useful to catch exceptions from the underlying.NET  framework and wrap it in your own exception and then  re-throw that to the user.  So in this case, I've got a property info, which is used  in reflection, then got a value, which has been set on a  target.  If there's an error inside that, perhaps the value doesn't  match the property type.  When an error happens, I'm catching that exception.  I'm adding some additional information to it.  So in this case, I'm giving the name of the property, which  calls the error.  And then I'm re-throwing that.  It's very important when you do this, when you re-throw an  exception, that you wrap it.  So in this case, I'm passing it to the constructor of my own  exception.  This preserves the stack trace.  Otherwise, whenever you throw a new exception, you throw away  the stack trace.  So in this case, the original exception will become an error  exception.  So when designing for extensibility, you want to use  virtual methods with care.  So there's two schools of thought with virtual exceptions.  There's one, which is make everything public, make  everything protected, nothing's private, everything's  virtual.  As a user can do exactly what they want, they can override  all the things.  And that way, your library is infinitely powerful.  The problem with that is it's quite easy to break existing  code with virtual methods.  You already saw in that previous case with the  constructor of virtual method in there, can cause issues.  So I'm of the opinion you want to use virtual methods with  care.  They're powerful, but they're dangerous.  And you need to put thought into how they're used.  So the other thing you want to think about when designing  for extensibility is prefer composition over inheritance.  So inheritance is very useful.  But composition is potentially much more powerful and  provides much more ability for users to customize how  something works.  So the case of JSON.net, the JSON sterilizer, there are  zero virtual methods on it.  All the extensibility to it is provided through other objects  that you can plug into it.  So you can plug in a reference resolver.  You can plug in a contract resolver.  You can plug in a trace write.  You can plug in your own custom JSON converters.  By doing that, you're also encouraging reusability.  People can implement their own reference resolvers,  contract resolvers, JSON converters.  And then they can publish those to the web.  And then other people can use those and plug those in  within their own applications.  So the final thing we'll look at is  designing for performance.  So a lot of the key things for designing performance  have actually already covered.  So lazy constructors.  So you want to have your constructors just to  initialization.  You want to lazily defer work until it's needed.  Cheap properties.  So property should be fast.  You don't want to use exceptions for flow control.  Throwing exceptions is very slow if you're doing a lot of them.  So perhaps if you've got a web request and you only throw one  exception, that's fine.  If you're doing a web request and you've got a for each loop  and within each iteration you're throwing an exception  and that loop runs a thousand times.  Those a thousand of exceptions can certainly add up.  So avoid using exceptions for flow control.  Use exceptions just for when something actually does go wrong.  Use structs when appropriate.  If you're allocating tens of thousands of objects,  that can be fine.  But doing it within a high throughput web application,  you can create a lot of garbage collection which can  potentially slow your website right down when garbage  collection does happen.  You want to use async properly.  I'm not going to cover how to use it properly because that's  literally an hour in itself.  So that's the whole async await that's been introduced  from a newest version of.NET.  Doing it properly is very hard.  I recommend if you do have an API that does have long running  operations, look into how to use it properly.  And I think it's very important when designing for performance  to avoid harming API usability for internal performance gains.  So computers tend to get faster but your API is not going  to get more usable over time.  So even if it's slow today you might figure out a way to  make it faster and future internally.  But once you've published an API and people are using that API,  you've got no way to really take it back.  So some more information.  If you're curious about API design and you want to know more,  I really recommend this book.  It was written by Brad Abrams.  He turned that phrase the power of sameness and some other  people at Microsoft.  The most recent version of this, the framework design  guidelines, is a second edition.  It came out in 2008.  So although that was a little while ago,  the vast majority of it is still applicable today.  And I really recommend it.  And another great resource is this YouTube video.  It was put up by a guy at Google.  How to design a good API and why it matters.  And although Google, they're more C++ and Java and Python,  none of it is.NET specific.  A lot of the high level concepts are still applicable  and it's quite a good watch.  So that's everything I have for you today.  It looks like we're bang out of time.  I'm going to hang around to answer questions.  But other than that, you've been a great audience.  And I hope everyone has learned something.  And thank you very much.  Thank you. . . . .
James_Newton-King_-_Designing_Wonderful__0_419.png James_Newton-King_-_Designing_Wonderful__420_1007.png James_Newton-King_-_Designing_Wonderful__1008_2135.png James_Newton-King_-_Designing_Wonderful__2136_2279.png James_Newton-King_-_Designing_Wonderful__2280_2627.png James_Newton-King_-_Designing_Wonderful__2628_3311.png James_Newton-King_-_Designing_Wonderful__3312_4907.png James_Newton-King_-_Designing_Wonderful__4908_5015.png James_Newton-King_-_Designing_Wonderful__5016_5495.png James_Newton-King_-_Designing_Wonderful__5496_8627.png James_Newton-King_-_Designing_Wonderful__8628_9455.png James_Newton-King_-_Designing_Wonderful__9456_13907.png James_Newton-King_-_Designing_Wonderful__13908_13955.png James_Newton-King_-_Designing_Wonderful__13956_16295.png James_Newton-King_-_Designing_Wonderful__16296_17267.png James_Newton-King_-_Designing_Wonderful__17268_17819.png James_Newton-King_-_Designing_Wonderful__17820_19103.png James_Newton-King_-_Designing_Wonderful__19104_19511.png James_Newton-King_-_Designing_Wonderful__19512_19931.png James_Newton-King_-_Designing_Wonderful__19932_21227.png James_Newton-King_-_Designing_Wonderful__21228_21491.png James_Newton-King_-_Designing_Wonderful__21492_21575.png James_Newton-King_-_Designing_Wonderful__21576_22967.png James_Newton-King_-_Designing_Wonderful__22968_24035.png James_Newton-King_-_Designing_Wonderful__24036_28619.png James_Newton-King_-_Designing_Wonderful__28620_28787.png James_Newton-King_-_Designing_Wonderful__28788_28919.png James_Newton-King_-_Designing_Wonderful__28920_30071.png James_Newton-King_-_Designing_Wonderful__30072_32963.png James_Newton-King_-_Designing_Wonderful__32964_33671.png James_Newton-King_-_Designing_Wonderful__33672_36503.png James_Newton-King_-_Designing_Wonderful__36504_37127.png James_Newton-King_-_Designing_Wonderful__37128_37691.png James_Newton-King_-_Designing_Wonderful__37692_38867.png James_Newton-King_-_Designing_Wonderful__38868_41303.png James_Newton-King_-_Designing_Wonderful__41304_42203.png James_Newton-King_-_Designing_Wonderful__42204_42395.png James_Newton-King_-_Designing_Wonderful__42396_44039.png James_Newton-King_-_Designing_Wonderful__44040_45947.png James_Newton-King_-_Designing_Wonderful__45948_47999.png James_Newton-King_-_Designing_Wonderful__48000_48155.png James_Newton-King_-_Designing_Wonderful__48156_53663.png James_Newton-King_-_Designing_Wonderful__53664_54443.png James_Newton-King_-_Designing_Wonderful__54444_58259.png James_Newton-King_-_Designing_Wonderful__58260_63587.png James_Newton-King_-_Designing_Wonderful__63588_65051.png James_Newton-King_-_Designing_Wonderful__65052_69311.png James_Newton-King_-_Designing_Wonderful__69312_71927.png James_Newton-King_-_Designing_Wonderful__71928_72551.png James_Newton-King_-_Designing_Wonderful__72552_74711.png James_Newton-King_-_Designing_Wonderful__74712_79319.png James_Newton-King_-_Designing_Wonderful__79320_80375.png James_Newton-King_-_Designing_Wonderful__80376_80423.png James_Newton-King_-_Designing_Wonderful__80424_80483.png James_Newton-King_-_Designing_Wonderful__80484_82811.png James_Newton-King_-_Designing_Wonderful__82812_85403.png James_Newton-King_-_Designing_Wonderful__85404_88823.png James_Newton-King_-_Designing_Wonderful__88824_89639.png James_Newton-King_-_Designing_Wonderful__89640_90287.png James_Newton-King_-_Designing_Wonderful__90288_90443.png James_Newton-King_-_Designing_Wonderful__90444_90491.png James_Newton-King_-_Designing_Wonderful__90492_90935.png James_Newton-King_-_Designing_Wonderful__90936_90983.png James_Newton-King_-_Designing_Wonderful__90984_91043.png James_Newton-King_-_Designing_Wonderful__91044_91103.png James_Newton-King_-_Designing_Wonderful__91104_91175.png James_Newton-King_-_Designing_Wonderful__91176_93703.png