Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NodeDecodingStrategy, mirroring NodeEncodingStrategy #45

Merged
merged 10 commits into from
Mar 18, 2019
Merged

Add NodeDecodingStrategy, mirroring NodeEncodingStrategy #45

merged 10 commits into from
Mar 18, 2019

Conversation

regexident
Copy link
Contributor

@regexident regexident commented Dec 26, 2018

The way things are right now we cannot encode an XML string like this …

<element name="foo">
    <name>bar</name>
</element>

… due to XMLCoder picking one name over the other with no way of specifying "check for a name in the attributes" rather than "check for a name in the elements", e.g.

Also all other strategies exist as variants for encoding and decoding, never just one of them.

One change this PR introduces though is that from now on one has to specify through a nodeDecodingStrategy to read from an attribute. It doesn't happen automagically any more. Which it never should have, imho.

We (well, "I", I guess 😅) should probably add a section on the use of Node(En/De)codingStrategy to the README, given that with this change (a necessary one, imho) existing code might not work any more.

@@ -246,68 +230,4 @@ final class NodeEncodingStrategyTests: XCTestCase {
("testKeyedContainer", testKeyedContainer),
("testUnkeyedContainer", testUnkeyedContainer),
]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stuff being tested here is not really relevant any more.


func testRSS() throws {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan to re-visit this test to enable it once all issues related to it have been resolved.

@codecov
Copy link

codecov bot commented Dec 26, 2018

Codecov Report

Merging #45 into master will increase coverage by 1.95%.
The diff coverage is 82.97%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #45      +/-   ##
==========================================
+ Coverage   74.98%   76.94%   +1.95%     
==========================================
  Files          37       37              
  Lines        1775     1804      +29     
==========================================
+ Hits         1331     1388      +57     
+ Misses        444      416      -28
Impacted Files Coverage Δ
Sources/XMLCoder/Auxiliaries/Box/UnkeyedBox.swift 100% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/BoolBox.swift 100% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/SharedBox.swift 100% <ø> (ø) ⬆️
...XMLCoder/Encoder/XMLUnkeyedEncodingContainer.swift 23.4% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/UIntBox.swift 100% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/StringBox.swift 100% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/IntBox.swift 100% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/Box.swift 100% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift 100% <ø> (ø) ⬆️
Sources/XMLCoder/Auxiliaries/Box/NullBox.swift 100% <ø> (ø) ⬆️
... and 8 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 85a4e01...d71e541. Read the comment docs.

@MaxDesiatov
Copy link
Collaborator

MaxDesiatov commented Jan 18, 2019

Sorry for the delay on this @regexident. I'm not quite sure that merging this as is would improve experience of users of XMLCoder. I'm currently inclined to think that both nodeDecodingStrategy and nodeEncodingStrategy are not the best option to configure this behaviour.

Personally, I would like to avoid the breakage, so maybe we could leave the automagical behaviour and use the explicit configuration only when it's available? Making this required would add a significant amount of code to CoreXLSX and will require effort from other users I believe.

In general .node{De,En}codingStrategy is not so good in a sense that it couples this configuration with the decoder and encoder. Shouldn't the "model" type decide what's the best way to map the properties to elements/attributes/content? If you have a ton of types to decode/encode, configuring this behaviour with a single closure is quite tedious, even when you work around it with some helper methods.

Here's an RFC for an API that could look like this:

enum XMLCodingStrategy {
  case element
  case attribute
  case content
}

protocol XMLDecodable: Decodable {
  func decodingStrategy(for: CodingKey) -> XMLCodingStrategy
}

protocol XMLEncodable: Encodable {
  func encodingStrategy(for: CodingKey) -> XMLCodingStrategy
}

Then it means types that don't conform to these protocols rely on existing automagical behaviour, while types that declare these, will provide explicit configuration at the point of their declaration.

What do you folks think?

@regexident
Copy link
Contributor Author

I too am far from happy with the way node-encodings are handled in both, XMLCoder, as well as format-specific strategies being handled in Codable as a whole.

Imho neither func encode(to encoder: Encoder) throws, nor init(from decoder: Decoder) throws should ever contain any format-specific logic, so I can understand why strategies were moved onto Encoder/Decoder.
But the way Codable basically gives you a choice to either provide a one-size-fits-all (e.g. "use date format XYZ everywhere") strategy or a customized strategy that's tightly coupled to the respective coding-path (which to add insult to injury is broken) is a shame. It's a serious weakness of the Codable API, imho.

Codable should not have been stabilized in its current state. There are just so many severely limiting factors to it that are the result of having been tightly designed with (only?) JSON in mind.

Anyway, your RFC for a protocol-based solution seems like a reasonable approach to me. 👍

…e-decoding-strategy

# Conflicts:
#	Sources/XMLCoder/Decoder/XMLDecoder.swift
#	Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift
#	Sources/XMLCoder/Decoder/XMLUnkeyedDecodingContainer.swift
#	Sources/XMLCoder/Encoder/XMLEncoder.swift
#	Sources/XMLCoder/Encoder/XMLKeyedEncodingContainer.swift
#	Sources/XMLCoder/Encoder/XMLUnkeyedEncodingContainer.swift
#	Tests/XMLCoderTests/BooksTest.swift
#	Tests/XMLCoderTests/NodeEncodingStrategyTests.swift
#	Tests/XMLCoderTests/RJITest.swift
#	XMLCoder.xcodeproj/project.pbxproj
@MaxDesiatov
Copy link
Collaborator

MaxDesiatov commented Mar 17, 2019

I've merged master into this and changed the behaviour to be compatible with previous "automagical" default decoding strategy, which uses NodeDecoding case called elementOrAttribute, reflecting a similar case both previously added to NodeEncoding. This should unblock me with #85.

@MaxDesiatov MaxDesiatov merged commit b8deb55 into CoreOffice:master Mar 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants