In Bloch’s presentation, he said designer should look for good power-to-weight ratio for API. Moreover, he also stressed that ‘Conceptual weight more important than bulk’. I guess the weight is for ‘Conceptual weight’, bulk is for number of methods of a class.
But I couldn’t understand what ‘Conceptual weight’ is, what ‘power-to-weight ratio’ is. Welcome to any explanation!
Bloch gave an example: List.subList() has good 'power-to-weight ratio'. If clients wants to know an index of a sub list, he doesn't need to call a low 'p2w ratio' method indexOfSubList(a,b,e), instead, he could call List.subList(a,b).indexOf(e). Bloch thought this is 'power-to-weight ratio'.
Origin:
API Should Be As Small As Possible But No Smaller
API should satisfy its requirements
When in doubt leave it out
Functionality, classes, methods, parameters, etc.
You can always add, but you can never remove
Conceptual weight more important than bulk
Look for a good power-to-weight ratio
I'd interpret "conceptual weight" as the number of abstract concepts you have to learn and understand to use the API. Concepts usually map to public classes, while classes that are not public add to the bulk but not to the conceptual weight.
So if you put it technically, an API has a high conceptual weight if a typical client of the API has to explicitly use a lot of classes belonging to the API to work with it.
"good power-to-weight ratio" then means the API should use as few public classes as possible to offer as much functionality as possible. That means an API should:
Not add concepts or abstractions of its own that are not present in the domain
For complex domains, offer shortcuts to the most commonly needed functionality that allows a typical user to bypass the more complex parts of the domain
I'd say that
power = the amount of functionality provided by the API
weight = the effort required to learn the API
I guess that an API with a good power-to-weight ratio is an API that offers a lot of functionality (power) while requiring little effort to properly work (weight) with it.
This is could be done via, for example, "Convention over Configuration". (Note this is just an example, and you can achieve this in many ways.)
It would be helpful a link to Bloch's presentation, he might be referring to something else :-)
He's referring to all the stuff you get from using an API. His example is for the collections API where each time you access it, you only get specific functionality. On the other hand, some API's will load much more stuff just to give you some functionality.
Another essential aspect of the power-to-weight ratio of an API or even a language as a whole is its verbosity. That is, how much you have to type to get a task done and the readability of the resulting code. In Java, Iterator has a better power-to-weight ratio than Enumeration, the interface it was designed to replace, simply because Iterator has a shorter name and shorter method names, which are no longer than they need to be and do the same job with no loss of clarity (as well as the additional remove method).
Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
I am already aware about the best practices for internationalizing/localizing an application so that it is consumable by maximum number of users - from geography, language and locale perspective. My question is - what are the (additional ?) best practices I need to follow if I want to make it easy for developers from across the world to consume my API?
I realize this question is very broad - so I will attempt to reduce the scope: I am particularly interested in creating a REST API and a Java client library for the aforementioned REST API.
Some of the things that come to mind are:
Provide a way for the developer to localize Strings (obvious)
Provide a way for the developer to customize locale-specific artifacts (measurements, units like currency, distance, weights etc)
Internationalize the API documentation (?? - is this done often? Is it practical?)
Beyond these measures, there are other aspects that really confuse me.
Correctness versus Simplicity:
Should I really name my classes to reflect the technical concepts on which they are based? For example, many of the design patterns may make sense to people who are well versed in English, but for developers with a different medium of instruction, they might be difficult to grasp. So, should I, in the interest of simplicity, rename DelegationInterceptor to something using simpler language? I'm wondering whether this simplification might have any (legal ??) consequences ?
Being Culture-Neutral:
Many-a-times, the easiest way for a developer to understand things is to see an example (or even a framework name) that is similar to something they see every day - which is why Pizzeria or Token Rings would be cool as example usages of my API. On the other hand, these same concepts may not be heard of in a country where most of the developers who develop to your API come from. So should I make generic examples? But then, what good are dull, boring, "generic" examples?
It'd be great if anyone could point me to any API's out there which do a good job of catering to developers from varied locales and cultures - not necessarily in the REST or Java space - anything will do.
My 3 cents: i18n best practices are not restricted to "geography, language and locale perspective". I even think that the most interesting aspect of i18n is getting to know and understand different cultures with all their richness.
To answer your question shortly: there is a book on API design written by Krzysztof Cwalina (nice first name, isn't it?) and Brad Abrams called Framework Design Guidelines. There is also some presentation on slideshare.
Anyway, I read the book and I think it is great, eye opening at least.
The longer answer... What you are referring to, is a Programming Usability. I haven't actually seen the topic covered in details (yet), but you can find many articles on Usability of Programming Languages (i.e. these slides). It seems this is pretty new discipline and the one that is pretty hard (it is a mixture of psychology, linguistics, grammar in two different sense, theory behind compilers, algorithmic, ... , and more). The most important would be of course human factor, especially inherent ability to produce errors.
Very interesting topic :)
Going through details of your question:
There is no way to create L10n API, as Localization is a process of adapting the software to local market needs. What you want to create is i18n-related API.
I don't necessary know why it has to be REST API, but to be 100% honest I am afraid that you might want to create some super-fantastic API that is actually against i18n best practices. The first things first: if you want it to be consumed by many developers, it should be regular API just like ICU. Maybe some parts of it could be exposed as RESTful API, but I am not sure why you want to do this.
As I already mentioned, there is something called ICU, especially ICU4J. I know that this API is extremely complex and not very developer-friendly, but it has one very important advantage: it does exist. And it was created by i18n experts, so it really follows best practices. Some parts are inherently complex because of nature of things - they just have to be if you want to implement the cultural support correctly. Sorry.
By the way: I might be wrong, but you said REST API, which rings a bell in my head. I believe you think of i18n support on the client side, don't you? In such case, I must ask one question: what is wrong with Globalize and/or Dojo and why you think it is better option to do everything on the server side?
OK, with Dojo I can answer the question myself: size and responsiveness.
Going through your points: "Provide a way for the developer to localize Strings (obvious)". It is not so obvious. That is, it is not as easy as you might think. If you want to do the obvious, you must be sure to understand the terms: Resource Model, Resource Organization, Locale Fall-back, Message Formatting, Machine Translation and Translation Memory.
Trust me, it is really easy to do a mistake here. On one hand, I doubt that anyone could create an API that will stop regular programmers from being lazy and hardcode strings, I doubt that it will ever happen. On the other hand, your friendly API (if you could achieve this) could easily allow reusing translations (which is i18n defect if it doesn't regard to common things like "OK", "Cancel", etc.). Also, you need to think of formatting capability so that it is (almost) impossible to introduce concatenations (very common i18n defect, preventing correct translations) and at the same time it is easy to handle multiple plural forms (still think you know best practices...?).
Proper organization and valid abstract model might help with implementation of TM and MT (that is reusing of old translations and minimizing the costs of new ones). But this is hard and very few people do it correctly (there are even some frameworks, like Play for example that implement serious misconceptions, i.e. single translation file only).
"Provide a way for the developer to customize locale-specific artifacts (measurements, units like currency, distance, weights etc)". Great idea. But please make sure that you will include formats as well. I mean that number format varies, unit varies, unit name and symbols (even for the same units) varies, but also unit placement may vary.
Some of these artifacts are already in ICU and CLDR, but for others you would actually need to get valid translations of patterns and items themselves.
From my experience it might be hard to collect the translations in the first place, yet valid ones...
"Internationalize the API documentation". Let me guess: you meant Localize, which in that case would probably be equal to Translate.
To be honest, I don't think that translating documentation of some API or Framework is all that important. Professional programmers have to have some command of English, at least be able to understand the technical documentation and write passable code (in terms of variable names and comments) - it is very unprofessional not to use English for such items.
"Correctness vs. Simplicity". I am not sure what kind of correctness you refer to. In terms of English language grammar, I would definitely favor simplicity over language correctness.
In terms of valid support for i18n, there are so many incorrect libraries already, please refrain from providing another one. As I wrote before, some things are inherently complex and they could be either done correctly (that will result in a complex API) or should not be done at all. Bringing simple, but only partially correct solution for cultural support will result in large number of defects (that I will curse you for) and the need to find even more complex workarounds. It is not worth the effort.
"Being culture neutral". Please read the book, I recommended. It covers this shortly (there is no need to go deeper, actually).
I doubt you should actually strive so much for political correctness, just avoid something you are sure my hurt somebody's feelings (don't do to others what you don't want to do unto you). That's it.
EDIT: Just two more things.
It might be a good idea to actually perform Usability tests on your API (just like you would do for User Interface). If it feels natural and intuitive, you did a great job. By doing that, you will also learn how people might want to use your library, that is you will discover additional use cases.
It is probably much harder to create programming library than to actually create a program. In case of library/API you often need to break truths that are (or at least seem to be) carved into stone, that is create something that is against common OOP/OOD principles, but is easy to use. You would also need to provide more overloads (there are many different use cases, mind you). Something as simple as formatting Date/Time in Java could really give you a headache if you want to support java.util.Date, Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, XMLGregorianCalendar, Joda Time and JSR-310.
As a side not, I am not sure if sending formatted date/times over REST API is actually the i18n best practice...
I have a complex system to design.
I have two ways:
Top-down: I will design many interfaces and contracts. Afterwords, I will implement these interfaces, and write a prototype to verify the design.
Bottom-up: I will write code to make the system run. Afterwords, I will extract interfaces and contracts from solid code. The distilled interfaces and contracts is my design. It's rule "make it run, make it right".
What is better way? From my opinion, I will choose Bottom-up. Because Top-down is very difficult, no one can design many interfaces at high abstract level,at least it's hard for me. When I write solid implementation to verify the initial design, there are many unreasonable things which force me to re-design from scratch. While I use Bottom-up, I feel quite "safe", it can run at least.
As others have said, it's usually a mix. On a more practical level, the following approach usually helps:
Start by going ABSTRACT Top-Down. Namely, break the system/design into logical components to solve tasks. But don't design precise finalized interfaces for those components. Proceed recursively till some components you arrive at are of "implementation-possible" size (e.g. are the size of a single function/method/class)
Then, go through the resultant component list Bottom-Up, and start designing first draft of interfaces/contracts.
Then, go through the resultant component list Bottom-Up, and start implementing them. This will allow you to:
Have a working and testable code immediately (no need to wait for underlying components to be implemented to test)
You can synthesize the final version of interfaces/contracts for higher level components based on the needs of the already-completed lower level components.
Except in most trivial designs nothing is ever this simplistic. I find that most designs require a mixture of both methodologies to refine.
In my opinion, top-down design is more natural than bottom-up one. E.g.: when you are designing a system, primarly you define its functionality(design interfaces and contracts), then you specify the entities of the system, implement relations among them and so on... Certainly, top-down design is more difficult than bottom-up one, and it requires experienced developers.
I personally also prefer Bottom up - first because you always forget something when doing top-down and then have to fix that and second because at least in my case I get lots of good ideas for the complete system while designing the single components from bottom.
Greetings,
Lorenz
In the real world is nearly impossibile to use these simplistic methodologies to design systems. You usally have to use both of them in multiple iterations.
But this is a simplistic answer, too.
Not sure if the title captures what I'm trying to say here.
When designing in OO should I be splitting my objects up into their most specific areas - so if I have a factory object that deals with creating objects but later on i come across a way of creating objects for another purpose even though they may be the same objects is it worth creating a seperate fcatory or just add to the exsiting.
My biggest worry is bulking up classes with tons of stuff, or splitting objects and diluting my projects into a sea of classes.
Any help?
EDIT:
I guess on a side note/sub topic part of me wants to find out the level of granularity you should use in a program. Kind of, how low should you go?
My biggest worry is bulking up classes with tons of stuff, or
splitting objects and diluting my
projects into a sea of classes
This is a very valid point and in any even reasonably sized project, extremely difficult to get right up front especially because realistically, requirements themselves evolve over time in most cases.
This is where "Refactoring" come in. You design based on what you know at any given point and try not too make too many leaps of faith as to what you think the system MAY evolve to.
Given that you know what you are building right now, you design your classes trying to make the best possible use of OO concepts - eg encapsulation / polymorphism. This is itself, like others have noted as well, can be notoriously difficult to achieve and thats where experience, both in designing OO systems as well as knowledge of the domain can really come in handy.
Design based on what you know --> Build It --> Review it --> Refactor it --> Re-design --> and it goes on and on..
Finding the correct level of detail and responsibility is what makes OOP design so difficult. We can help you with a specific case but not with anything this general. If there were algorithms or strict methodologies of how to solve this, everyone could be an OOP designer.
A rule of thumb I like for deciding "is this getting too big now?" is "can I explain the purpose of it concisely?" If you start having to introduce caveats and lots of weasel words to explain the functions of a component of your design (be it class, member variable, method or whatever) it might be a good indicator that it's getting too complex and should be split up.
In your specific case, if you already have a factory object then the DRY Principle (Don't Repeat Yourself) would say that it's a bad idea to create another factory that does the same thing.
Is this an actual problem that you face? Or merely a fear about how your code might grow in the future?
If you are using the same type of object to solve drastically different problems then you may need to redesign the class to focus on seperation of concerns. If you need a more specific answer, you will need to provide an example of a type of class that would need this functionality.
I might have worded things badly in
the Q. I guess I wouldnt be repeating
myself its just more of a case of
where to put the code, it could be
added to an exsiting factory that
creates design objects for exporing
data to excel spreadsheets. On the
other hand I could see it could also
have its own factory for importing
excel data. Both factories would
produce the same objects but the inner
workings are completely different. –
If you aren't doing or plan on doing any class abstraction (subclassing or using interfaces) you may not need to use the factory pattern at all. The factory pattern is generally best suited for supplying objects of a base class type or that implement a specific interface.
Both
factories would produce the same
objects but the inner workings are
completely different.
Not sure if I've understood you correctly, but this sounds like a candidate for the AbstractFactory pattern.
I’m currently learning the Java Collections API and feel I have a good understanding of the basics, but I’ve never understood why this standard API doesn’t include a Graph implementation. The three base classes are easily understandable (List, Set, and Map) and all their implementations in the API are mostly straightforward and consistent.
Considering how often graphs come up as a potential way to model a given problem, this just doesn’t make sense to me (it’s possible it does exist in the API and I’m not looking in the right place of course). Steve Yegge suggests in one of his blog posts that a programmer should consider graphs first when attacking a problem, and if the problem domain doesn’t fit naturally into this data structure, only then consider the alternative structures.
My first guess is that there is no universal way to represent graphs, or that their interfaces may not be generic enough for an API implementation to be useful? But if you strip down a graph to its basic components (vertices and a set of edges that connect some or all of the vertices) and consider the ways that graphs are commonly constructed (methods like addVertex(v) and insertEdge(v1, v2)) it seems that a generic Graph implementation would be possible and useful.
Thanks for helping me understand this better.
Note that some special graphs are included in the Collection Framework, notably linked lists and trees.
This also points to a possible reason why no general Graph implementation is present: as graphs can have so many different forms and flavours with wildly different characteristics, a general Graph might not turn out to be very useful.
Also, at least in my practice so far, I haven't felt the need for graphs most of the time. Some domains surely do need them, but many simply don't. (Out of more than a dozen projects in various domains I have been involved in so far, I recount two which actually needed graphs.) So I guess there was no really big pressure from the Java community in general to have a Graph in the Collection Framework. It contains only the basic stuff, which is needed "almost always", by "almost everyone". And one of its strengths is indeed its (relative) simplicity and clarity, which, I believe, its designers see as an asset to be preserved.
First of all, I have a very superficial knowledge of SAP. According to my understanding, they provide a number of industry specific solutions. The concept seems very interesting and I work on something similar for banking industry. The biggest challenge we face is how to adapt our products for different clients. Many concepts are quite similar across enterprises, but there are always some client-specific requirements that have to be resolved through configuration and customization. Often this requires reimplementing and developing customer specific features.
I wonder how efficient in this sense SAP products are. How much effort has to be spent in order to adapt the product so it satisfies specific customer needs? What are the mechanisms used (configuration, programming etc)? How would this compare to developing custom solution from scratch? Are they capable of leveraging and promoting best practices?
Disclaimer: I'm talking about the ABAP-based part of SAP software only.
Disclaimer 2, ref PATRYs response: HR is quite a bit different from the rest of the SAP/ABAP world. I do feel rather competent as a general-purpose ABAP developer, but HR programming is so far off my personal beacon that I've never even tried to understand what they're doing there. %-|
According to my understanding, they provide a number of industry specific solutions.
They do - but be careful when comparing your own programs to these solutions. For example, IS-H (SAP for Healthcare) started off as an extension of the SD (Sales & Distribution) system, but has become very much more since then. While you could technically use all of the techniques they use for their IS, you really should ask a competent technical consultant before you do - there are an awful lot of pits to avoid.
The concept seems very interesting and I work on something similar for banking industry.
Note that a SAP for Banking IS already exists. See here for the documentation.
The biggest challenge we face is how to adapt our products for different clients.
I'd rather rephrase this as "The biggest challenge is to know where the product is likely to be adapted and to structurally prepare the product for adaption." The adaption techniques are well researched and easily employed once you know where the customer is likely to deviate from your idea of the perfect solution.
How much effort has to be spent in
order to adapt the product so it
satisfies specific customer needs?
That obviously depends on the deviation of the customer's needs from the standard path - but that won't help you. With a SAP-based system, you always have three choices. You can try to customize the system within its limits. Customizing basically means tweaking settings (think configuration tables, tens of thousands of them) and adding stuff (program fragments, forms, ...) in places that are intended to do so. Technology - see below.
Sometimes customizing isn't enough - you can develop things additionally. A very frequent requirement is some additional reporting tool. With the SAP system, you get the entire development environment delivered - the very same tools that all the standard applications were written with. Your programs can peacefully coexist with the standard programs and even use common routines and data. Of course you can really screw things up, but show me a real programming environment where you can't.
The third option is to modify the standard implementations. Modifications are like a really sharp two-edged kitchen knife - you might be able to cook really cool things in half of the time required by others, but you might hurt yourself really badly if you don't know what you're doing. Even if you don't really intend to modify the standard programs, it's very comforting to know that you could and that you have full access to the coding.
(Note that this is about the application programs only - you have no chance whatsoever to tweak the kernel, but fortunately, that's rarely necessary.)
What are the mechanisms used (configuration, programming etc)?
Configurations is mostly about configuration tables with more or less sophisticated dialog applications. For the programming part of customizing, there's the extension framework - see http://help.sap.com/saphelp_nw70ehp1/helpdata/en/35/f9934257a5c86ae10000000a155106/frameset.htm for details. It's basically a controlled version of dependency injection. As a solution developer, you have to anticipate the extension points, define the interface that has to be implemented by the customer code and then embed the call in your code. As a project developer, you have to create an implementation that adheres to the interface and activate it. The basic runtime system takes care of glueing the two programs together, you don't have to worry about that.
How would this compare to developing custom solution from scratch?
IMHO this depends on how much of the solution is the same for all customers and how much of it has to be adapted. It's really hard to be more specific without knowing more about what you want to do.
I can only speak for the Human Resource component, but this is a component where there is a lot of difference between customers, based on a common need.
First, most of the time you set the value for a group, and then associate the object (person, location...) with a group depending on one or two values. This is akin to an indirection, and allow for great flexibility, as you can change the association for a given location without changing the others. in a few case, there is a 3 level indirection...
Second, there is a lot of customization that is nearly programming. Payroll or administrative operations are first class example of this. In the later cas, you get a table with the operation (hiring for example), the event (creation, modification...) a code for the action (I for test, F to call a function, O for a standard operation) and a text field describing the parameters of a function ("C P0001, begda, endda" to create a structure P001 with default values).
Third, you can also use such a table to indicate a function or class (ABAP-OO), that will be dynamically called. You get a developer to create this function or class, and then indicate this in the table. This is a method to replace a functionality by another one, or extend it. This is used extensively in the ESS/MSS.
Last, there is also extension point or file that you can modify. this is nearly the same as the previous one, except that you don't need to indicate the change : the file is always used (ZXPADU01/02 for HR modification of infotype)
hope this help
Guillaume PATRY