Document the public API
What
The public API needs to be documented to make it clear what is intended for user access (i.e. cannot be broken without a major version bump), and what is internal to the library.
Why
So that we know what can and cannot be altered without breaking backwards-compatibility when making internal changes to the library or adding new features.
Public API (6.0.0)
As of 6.0.0, I think that the public API of json-schema comprises the following. Anything not in this list should be able to be changed in any manner without bumping the major version number, provided it does not impact the behavior of the stuff listed here in a non-backwards-compatible manner.
Methods
Validator
Validator::__construct- create a validator instance with a custom factoryValidator::validate- main entry point for validationValidator::check- BC alias ofvalidate(pre-5.0.0), does not pass$valueby referenceValidator::coerce- BC alias ofvalidate(pre-5.0.0), setsCHECK_MODE_COERCE_TYPESValidator::getErrors- get array of validation errorsValidator::numErrors- get number of validation errorsValidator::getErrorMask- get the error categoriesValidator::isValid- get overall validation statusValidator::reset- reset validation status
Factory
Factory::__construct- create aFactoryinstance with customSchemaStorage,UriRetrieveror$checkmodeFactory::setConfig- overwrite$checkModeFactory::getConfig- get$checkModeor a filtered subsetFactory::addConfig- add options to$checkModeFactory::removeConfig- remove options from$checkModeFactory::getSchemaStorage- get the currentSchemaStorageinstanceFactory::getUriRetriever- get the currentUriRetrieverinstance
SchemaStorage & SchemaStorageInterface
SchemaStorage::__construct- create aSchemaStorageinstance with customUriRetrieverorUriResolverSchemaStorage::addSchema- add a schema to the storage instance by identifyng URISchemaStorage::getSchema- get a schema from the storage instance by identifying URI
UriResolver & UriResolverInterface
UriResolver::resolve- resolve a URI to absolute
UriRetriever & UriRetrieverInterface
UriRetriever::retrieve- retrieve & return a decoded JSON schema object
Class Constants
Validator::SCHEMA_MEDIA_TYPE- official JSON schema media typeValidator::ERROR_*- error categories (bitmask)Constraint::CHECK_MODE_*- validation options (bitmask)
Class Properties
Validator::$factory- dependency injection, state & instance management
Data Formats
- The array data returned by
Validator::getErrors()
Exceptions
InvalidArgumentExceptionInvalidConfigExceptionInvalidSchemaExceptionInvalidSchemaMediaTypeExceptionInvalidSourceUriExceptionJsonDecodingExceptionResourceNotFoundExceptionRuntimeExceptionUnresolvableJsonPointerExceptionUriResolverExceptionValidationException
Please let me know if I have missed anything, or if anything in the list above needs changing. I'm fully aware that there are public methods which are not in this list - I deliberately omitted stuff I felt should not be considered part of the public API, so if you think I've omitted something that should be included, sing out!
Also, if this happens, then there will also be methods on that class which need to be considered part of the public API.
Some food for thought: http://fabien.potencier.org/pragmatism-over-theory-protected-vs-private.html
Fabien makes some good points about protected methods also implicitly being part of the public API of a project. It's more pronounced in a project like Symfony of course, but the core points stand that for example BaseConstraint::$factory is also part of the public API as someone might inherit their own validator from Validator, giving them protected access to that property. That would cause breakage if it were changed in a minor/patch update.
If you wish to restrict this it could be a good idea to make the property itself private and have a protected getter.
@curry684 Unfortunately, the way this project is architected means that there will always be methods that are not part of the public API, which are declared as public or protected. No way to avoid that other than significant refactoring of the library that will break a lot of people's workflows.
From your link:
By the way, public methods does not define the public API. Sometimes, you need to declare a method as public because you need to access it from another class in your library; but that does not mean that you want your users to actually call it directly. What do you do then? Symfony and Flow3 have decided to mark the "real" public API with the @api tag. All classes, methods, and properties tagged with @api are public in the sense that we guarantee their stability over time: their name, signature, and behavior won't change for any minor version of the library. That's a strong commitment; one that I like much better than any strict enforcement done on the language level.
This is the kind of thing I'm going for here - to have a well-documented public API, and thereby avoid the confusion that may arise from relying solely on the accessibility to determine whether or not something is part of the API (which won't work for this library in its current architecture).
...for example BaseConstraint::$factory is also part of the public API as someone might inherit their own validator from Validator, giving them protected access to that property.
This is a very good point - I'll need to go through and see which properties need to available for inheritance, and which do not. I have no objection in principle to certain protected properties being considered part of the public API, but I would like to document them as such.
Although, adding a getter for Validator::$factory does sound like an increasingly good idea, and would be consistent with how other classes are managing their own injectable dependencies. I will probably do this. Can't make it private though; that would break things.
That was my main intent with giving the food for thought: you are both working towards a new major version and documenting the API. That is the best time, if any, to evaluate all extension points that ever happened to get created, intentionally or not. In 6.0 it's perfectly acceptable to change a property from protected to private and give it a protected getter instead. Internal breakage should be zero with a proper refactoring tool.
This proposal works for me as a first phase for documentation
Closing this issue for now since there isn't any ask for it and we are very bound for time/contribution.