{"action":"created","issue":{"url":"https://api.github.com/repos/lightbend/kafka-streams-scala/issues/52","repository_url":"https://api.github.com/repos/lightbend/kafka-streams-scala","labels_url":"https://api.github.com/repos/lightbend/kafka-streams-scala/issues/52/labels{/name}","comments_url":"https://api.github.com/repos/lightbend/kafka-streams-scala/issues/52/comments","events_url":"https://api.github.com/repos/lightbend/kafka-streams-scala/issues/52/events","html_url":"https://github.com/lightbend/kafka-streams-scala/pull/52","id":298689955,"number":52,"title":"Add a typesafe-by-default implementation for kafka-streams-scala","user":{"login":"ssaavedra","id":581152,"avatar_url":"https://avatars2.githubusercontent.com/u/581152?v=4","gravatar_id":"","url":"https://api.github.com/users/ssaavedra","html_url":"https://github.com/ssaavedra","followers_url":"https://api.github.com/users/ssaavedra/followers","following_url":"https://api.github.com/users/ssaavedra/following{/other_user}","gists_url":"https://api.github.com/users/ssaavedra/gists{/gist_id}","starred_url":"https://api.github.com/users/ssaavedra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ssaavedra/subscriptions","organizations_url":"https://api.github.com/users/ssaavedra/orgs","repos_url":"https://api.github.com/users/ssaavedra/repos","events_url":"https://api.github.com/users/ssaavedra/events{/privacy}","received_events_url":"https://api.github.com/users/ssaavedra/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-02-20T17:55:35Z","updated_at":"2018-02-21T15:54:06Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https://api.github.com/repos/lightbend/kafka-streams-scala/pulls/52","html_url":"https://github.com/lightbend/kafka-streams-scala/pull/52","diff_url":"https://github.com/lightbend/kafka-streams-scala/pull/52.diff","patch_url":"https://github.com/lightbend/kafka-streams-scala/pull/52.patch"},"body":"Enable a type *safer* API for kafka-streams.\r\n\r\nThis PR creates new abstractions (named `TS-` from the base objects in the underlying library) which enable a more type safe abstraction than the provided default.\r\n\r\nThis does not use the Perhaps pattern and requires some implicit value to be always present in order to call the methods, which ensures no compile-time errors are transformed into runtime exceptions where avoidable.\r\n\r\nYou can still perform unsafe operations by calling the `.unsafely` handler, which will perform your operation in the underlying data type and still wrap it into the type safe operator when finished, so if you import the UnsafelyWrapper implicit class you can still make use of the default Serdes, but you can't *by default* so you will catch serialization errors unless you explicitly request to avoid so."},"comment":{"url":"https://api.github.com/repos/lightbend/kafka-streams-scala/issues/comments/367372285","html_url":"https://github.com/lightbend/kafka-streams-scala/pull/52#issuecomment-367372285","issue_url":"https://api.github.com/repos/lightbend/kafka-streams-scala/issues/52","id":367372285,"user":{"login":"ssaavedra","id":581152,"avatar_url":"https://avatars2.githubusercontent.com/u/581152?v=4","gravatar_id":"","url":"https://api.github.com/users/ssaavedra","html_url":"https://github.com/ssaavedra","followers_url":"https://api.github.com/users/ssaavedra/followers","following_url":"https://api.github.com/users/ssaavedra/following{/other_user}","gists_url":"https://api.github.com/users/ssaavedra/gists{/gist_id}","starred_url":"https://api.github.com/users/ssaavedra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ssaavedra/subscriptions","organizations_url":"https://api.github.com/users/ssaavedra/orgs","repos_url":"https://api.github.com/users/ssaavedra/repos","events_url":"https://api.github.com/users/ssaavedra/events{/privacy}","received_events_url":"https://api.github.com/users/ssaavedra/received_events","type":"User","site_admin":false},"created_at":"2018-02-21T15:54:06Z","updated_at":"2018-02-21T15:54:06Z","author_association":"NONE","body":"Thank you for the comments.\r\n\r\n1. About the use of `implicit final` you are right, and according to SIP-15 all value classes should be implicitly considered final.\r\n\r\n2. About the second point, you remind me that I should add a test case for the `.unsafely { }` API, and you are right even though you didn't say it like that :slightly_smiling_face: \r\n\r\n3. Also, I can amend the test case you mention to include the `.unsafely` API call demonstrating the use of mixed serdes as something you can \"opt-in\" but is not there by default.\r\n\r\nBut regarding the rest, this approach assumes you don't want to use the default serdes (by default). My reasoning is that you don't gain anything by using the default serdes because the type system should find your implicit value for the appropriate one, and if it doesn't, then it should probably not compile, because otherwise you'd be using an inappropriate serde. We can discuss this point further if you want.\r\n\r\nA different approach is the one you've been implementing, using the Perhaps[T] mechanism to allow for unexistent implicits, but such approach creates runtime exceptions where there could be compile-time errors, and I think that's the main point of divergence in our respective points of view.\r\n\r\nAnother case could be made with a more heavy wrapper that could contain path-dependent types including the default serdes types, and use such default serdes only if no implicits are provided (or otherwise keep the default serde instances around and inject them as the explicit serdes), I'm not sure if my wording is clear. Something along the lines of this\r\n\r\n```scala\r\nclass AlternativeImplementationForKStreamS[K, V, DefaultK, DefaultV](inner: KStream[K, V],\r\n                                           defaultKSerde: Serde[DefaultK],\r\n                                           defaultVSerde: Serde[DefaultV]) {\r\n      def mapValues[VR](f: V => VR)\r\n                       (implicit materialized: Materialized[K, VR]) = ???\r\n\r\n      def mapValues[VR](f: V => DefaultV)\r\n                       (implicit ev: DefaultK =:= K) =\r\n        mapValues(f)(materializedFromSerde(defaultKSerde, defaultVSerde))\r\n    }\r\n```\r\n\r\nI look forward to your comments on this. I'll push a new commit on the PR soon.\r\n\r\nAlso, thanks for taking a look at this!"}}
{"actor":{"display_login":"ssaavedra"}}