How could an idiomatic design of Serializable/Cloneable/... look like in Scala? - java

I wonder how much different these funcionality would look like (and how different the implementation would be), if Scala wouldn't (have to) follow Java's java.io.Serializable/java.lang.Cloneable (mostly to stay compatible with Java and the tools/ecosystem around it).
Because Scala is more simpler in language design, but enables more powerful implementation and abstraction possibilities, it is thinkable that Scala might take a different path compared to Java, if it wouldn't have to shoulder the Java-compatibility-burden.
I could imagine that a idiomatic implementation would use type classes or traits with (possibly) private fields/methods (not possible in Java interfaces?), maybe carrying some standard implementation?
Or are marker interfaces still the right choice in Scala?

Serialization and cloning are both kind of special because of mutability:
Serialization, because it has to deal with cycles in the object graph, and;
Cloning because... Well, the only reason to clone an object is to prevent the accidental spread of mutable state.
So, if you're willing to commit to a completely immutable domain model, you don't have object graphs as such anymore, you have object trees instead.
For a functionally-oriented approach to serialization, SBinary is what I'd probably try first. For cloning, Just Don't Do It. :)

Or are marker interfaces still the right choice in Scala?
Nope. They aren't even the right choice in Java. They should be annotations, not interfaces.

the best way to do this in ideomatic scala is to use implicits with the effect of a typeclass.
This is used for the Ordered trait
def max[A <% Ordered[A]](a:A,b:A);
means the same as:
def max[A](a:A,b:A)(implicit orderer: T => Ordered[A]);
It says you can use every type A as long as it can be threated as an Ordered[A].
this has several benefits you don´t have with the interface/inheritance approach of Java
You can add an implicit Ordered definition to an existing Type. You can´t do that with inheritance.
You can have several implementation of Ordered for one Type! This is even more flexible than Type classes in Haskell wich allow only one instance per type.
In conclusion scalas implicits used together with generics enable a very flexible approach to define Constraints on types.
It is the same with cloneable/serializable.
You may also want to look at the scalaz library which adds haskell like typeclasses to Scala such as Functor, Applicative and Monad and offers a rich set of implicits so that this concepts can also enrich the standart library.

Related

Turning abstract class without fields to interface (Java, Sonar rule s1610)

I refer to this rule:
With Java 8's "default method" feature, any abstract class without direct or inherited field should be converted into an interface.
In my perception default + private methods in Java8+ interfaces is a
pure compromise JDK designers took in order to solve a dilemma they faced: they had to introduce new methods (for ex. Map interface)
without breaking old code that used those interfaces (backward
compatibility).
In practice JDK designers introduced implementation inheritance in places
where interface inheritance existed, so potentially they
increased coupling and brittleness of our existing and future code.
In my perception introduced implementation inheritance now diminishes cool nature of interfaces - the multiple inheritance.
I understand why "abstract classes without fields" is mentioned in Sonar rule. By this the authors of the rule do lessen brittleness (but don't eliminate the fact of implementation inheritance). Compare to problems of Scala traits that do permit fields (new Java interfaces look more and more like Scala's traits) - Scala lang designers tried to solve those problems with things like trait linearization, lazy vals, etc.
I'm avoiding arguments like "it is in JDK so it is a pattern", let us speak more at the conceptual level here.
Question: Could anyone explain me why Sonar promotes this, IMHO, flawed rule?
What do we gain by such a rule? What benefit/use case am I missing here?
Thanks.
I don't necessarily agree with the rule, but I see where it's coming from.
The thing is that you don't really lose anything in this case. The only time you'd run into problems with regard to multiple inheritance would be if you implemented several interfaces containing methods with the same signature and different implementations.
However, this is forbidden by Java (you'd need to provide your own implementation of that method), so there is no danger in doing so.
In general, interfaces are more versatile than classes, so it makes sense to use them if possible.
As a counter point, the interface default feature was introduced to allow adding methods to existing interfaces without breaking existing code, but that's not the case here.

Minimizing interfaces in Golang

In golang, interfaces are extremely important for decoupling and composing code, and thus, an advanced go program might easily define 1000s of interfaces .
How do we evolve these interfaces over time, to ensure that they remain minimal?
Are there commonly used go tools which check for unused functions ?
Are there best practices for annotating go functions with something similar to java's #Override, which ensures that a declared function is properly implementing a expected contract?
Typically in the java language, it is easy to keep code tightly bound to an interface specification because the advanced tooling allows us to find and remove functions which aren't referenced at all (usually this is highlighted automatically for you in any common IDE).
Are there commonly used go tools which check for unused functions ?
Sort of, but it is really hard to be sure for exported interfaces. oracle can be used to find references to types or methods, but only if you have all of the code that references you availible on your gopath.
can you ensure a type implements a contract?
If you attempt to use a type as an interface, the compiler will complain if it does not have all of the methods. I generally do this by exporting interfaces but not implementations, and making a constructor:
type MyInterface interface{
Foo()
}
type impl struct{}
func (i *impl) Foo(){}
func NewImpl() MyInterface{
return &impl{}
}
This will not compile if impl does not implement all of the required functions.
In go, it is not needed to declare that you implement an interface. This allows you to implement an interface without even referencing the package it is defined in. This is pretty much exactly the opposite of "tightly binding to an interface specification", but it does allow for some interesting usage patterns.
What your asking for isn't really a part of Go. There are no best practices for annotating that a function satisfies an interface. I would personally say the only clear best practice is to document which interfaces your types implement so that people can know. If you want to test explicitly (at compile time) if a type implements an interface you can do so using assignment, check out my answer here on the topic; How to check if an object has a particular method?
If you're just looking to take inventory of your code base to do some clean up I would recommend using that assignment method for all your types to generate compile time errors regarding what they don't implement, scale down the declarations until it compiles. In doing so you should become aware of the disparity between what might be implemented and what actually is.
Go is also lacking in IDE options. As a result some of those friendly features like "find all references" aren't there. You can use text searching tricks to get around this, like searching func TheName to get only the declaration and .TheName( to get all invocations. I'm sure you'll get used to it pretty quickly if you continue to use this tooling.

When is a reference to the object class required?

What is the function of the class Object in java? All the "objects" of any user defined class have the same function as the aforementioned class .So why did the creators of java create this class?
In which situations should one use the class 'Object'?
Since all classes in Java are obligated to derive (directly or indirectly) from Object, it allows for a default implementation for a number of behaviours that are needed or useful for all objects (e.g. conversion to a string, or a hash generation function).
Furthermore, having all objects in the system with a common lineage allows one to work with objects in a general sense. This is very useful for developing all sorts of general applications and utilities. For example, you can build a general purpose cache utility that works with any possible object, without requiring users to implement a special interface.
Pretty much the only time that Object is used raw is when it's used as a lock object (as in Object foo = new Object(); synchronized(foo){...}. The ability to use an object as the subject of a synchronized block is built in to Object, and there's no point to using anything more heavyweight there.
Object provides an interface with functionality that the Java language designers felt all Java objects should provide. You can use Object when you don't know the subtype of a class, and just want to treat it in a generic manner. This was especially important before the Java language had generics support.
There's an interesting post on programmers.stackexchange.com about why this choice was made for .NET, and those decisions most likely hold relevance for the Java language.
What Java implements is sometimes called a "cosmic hierarchy". It means that all classes in Java share a common root.
This has merit by itself, for use in "generic" containers. Without templates or language supported generics these would be harder to implement.
It also provides some basic behaviour that all classes automatically share, like the toString method.
Having this common super class was back in 1996 seen as a bit of a novelty and cool thing, that helped Java get popular (although there were proponents for this cosmic hierarchy as well).

Why ADTs are good and Inheritance is bad?

I am a long time OO programmer and a functional programming newbie. From my little exposure algebraic data types only look like a special case of inheritance to me where you only have one level hierarchy and the super class cannot be extended outside the module.
So my (potentially dumb) question is: If ADTs are just that, a special case of inheritance (again this assumption may be wrong; please correct me in that case), then why does inheritance gets all the criticism and ADTs get all the praise?
Thank you.
I think that ADTs are complementary to inheritance. Both of them allow you to create extensible code, but the way the extensibility works is different:
ADTs make it easy to add new functionality for working with existing types
You can easily add new function that works with ADT, which has a fixed set of cases
On the other hand, adding new case requires modifying all functions
Inheritance makes it easy to add new types when you have fixed functionality
You can easily create inherited class and implement fixed set of virtual functions
On the other hand, adding a new virtual function requires modifying all inherited classes
Both object-oriented world and functional world developed their ways to allow the other type of extensibility. In Haskell, you can use typeclasses, in ML/OCaml, people would use dictionary of functions or maybe (?) functors to get the inhertiance-style extensibility. On the other hand, in OOP, people use the Visitor pattern, which is essentially a way to get something like ADTs.
The usual programming patterns are different in OOP and FP, so when you're programming in a functional language, you're writing the code in a way that requires the functional-style extensibility more often (and similarly in OOP). In practice, I think it is great to have a language that allows you to use both of the styles depending on the problem you're trying to solve.
Tomas Petricek has got the fundamentals exactly right; you might also want to look at Phil Wadler's writing on the "expression problem".
There are two other reasons some of us prefer algebraic data types over inheritance:
Using algebraic data types, the compiler can (and does) tell you if you have forgotten a case or if a case is redundant. This ability is especially useful when there are many more operations on things than there are kinds of thing. (E.g., many more functions than algebraic datatypes, or many more methods than OO constructors.) In an object-oriented language, if you leave a method out of a subclass, the compiler can't tell whether that's a mistake or whether you intended to inherit the superclass method unchanged.
This one is more subjective: many people have noted that if inheritance is used properly and aggressively, the implementation of an algorithm can easily be smeared out over a half a dozen classes, and even with a nice class browser at can be hard to follow the logic of the program (data flow and control flow). Without a nice class browser, you have no chance. If you want to see a good example, try implementing bignums in Smalltalk, with automatic failover to bignums on overflow. It's a great abstraction, but the language makes the implementation difficult to follow. Using functions on algebraic data types, the logic of your algorithm is usually all in one place, or if it is split up, its split up into functions which have contracts that are easy to understand.
P.S. What are you reading? I don't know of any responsible person who says "ADTs good; OO bad."
In my experience, what people usually consider "bad" about inheritance as implemented by most OO languages is not the idea of inheritance itself but the idea of subclasses modifying the behavior of methods defined in the superclass (method overriding), specifically in the presence of mutable state. It's really the last part that's the kicker. Most OO languages treat objects as "encapsulating state," which amounts to allowing rampant mutation of state inside of objects. So problems arise when, for example, a superclass expects a certain method to modify a private variable, but a subclass overrides the method to do something completely different. This can introduce subtle bugs which the compiler is powerless to prevent.
Note that in Haskell's implementation of subclass polymorphism, mutable state is disallowed, so you don't have such issues.
Also, see this objection to the concept of subtyping.
I am a long time OO programmer and a functional programming newbie. From my little exposure algebraic data types only look like a special case of inheritance to me where you only have one level hierarchy and the super class cannot be extended outside the module.
You are describing closed sum types, the most common form of algebraic data types, as seen in F# and Haskell. Basically, everyone agrees that they are a useful feature to have in the type system, primarily because pattern matching makes it easy to dissect them by shape as well as by content and also because they permit exhaustiveness and redundancy checking.
However, there are other forms of algebraic datatypes. An important limitation of the conventional form is that they are closed, meaning that a previously-defined closed sum type cannot be extended with new type constructors (part of a more general problem known as "the expression problem"). OCaml's polymorphic variants allow both open and closed sum types and, in particular, the inference of sum types. In contrast, Haskell and F# cannot infer sum types. Polymorphic variants solve the expression problem and they are extremely useful. In fact, some languages are built entirely on extensible algebraic data types rather than closed sum types.
In the extreme, you also have languages like Mathematica where "everything is an expression". Thus the only type in the type system forms a trivial "singleton" algebra. This is "extensible" in the sense that it is infinite and, again, it culminates in a completely different style of programming.
So my (potentially dumb) question is: If ADTs are just that, a special case of inheritance (again this assumption may be wrong; please correct me in that case), then why does inheritance gets all the criticism and ADTs get all the praise?
I believe you are referring specifically to implementation inheritance (i.e. overriding functionality from a parent class) as opposed to interface inheritance (i.e. implementing a consistent interface). This is an important distinction. Implementation inheritance is often hated whereas interface inheritance is often loved (e.g. in F# which has a limited form of ADTs).
You really want both ADTs and interface inheritance. Languages like OCaml and F# offer both.

Why does the Collections class contain standalone (static) methods, instead of them being added to the List interface?

For all the methods in Collections that take a List as their first argument, why aren't those methods simply part of the List interface?
My intuition is: given a List object, that object itself should "know" how to perform on itself operations such as rotate(), shuffle(), or reverse(). But instead, as a Java programmer, I have to review both the methods in the List interface, as well as the static methods "over there" in the Collections class, to ensure I'm using a canonical solution.
Why were some methods placed as static standalone methods in the Collections class, instead of being added to the List interface (and presumably thus implemented by some existing or would-be base class)?
I'm trying to better understand the design decisions behind the Java collections framework.
Is there some compelling OO design principle here that I'm overlooking? Or was this distinction done simply for some practical, performance reason?
The point is that given suitable primitive operations (remove, set etc) a bunch of more high level operations (sort, shuffle, binary search) can be implemented once rather than being implemented by every single list implementation.
Effectively, java.util.Collections is like .NET's Enumerable class - full of general purpose methods which can work on any collection, so that they can share a single implementation and avoid duplication.
Rational Behind the List Interface's Methods
The List interface is a very core part of the Java runtime and is already a little onerous to fully implement all of the members when rolling out your own List implementations. So, adding extra methods that aren't directly related to the definition of a list is a bit extraneous. If you need those methods on a List implementation, why not subclass the interface and then require them?
If you where going to come along say in version 1.3 and add functionality to the List interface by adding new utility methods, you will break all past implementors of the interface.
From a Domain-Driven Design perspective, the utility methods in Collections are not part of the normal domain of a list.
Regarding OO design principals, I think it would be important to make the distinction between application OO design and language runtime OO design.
The authors of Java may do things very differently now that they have hindsight and perspective of many years of usage of the API. That said the C# IList interface is quite similar to Java's and C#'s authors did have the perspective.
It's certainly a judgement call at some level. I think the main trade-off to consider is this: When you add a method to an interface, every implementer of that interface must write code to implement it.
If the semantics of that method are such that different implementations of the interface will best implement those semantics in very different ways, then it's better to put it in the interface. (Of course, if the semantics simply can't be defined in terms of other methods in the interface, then it must be its own method in the interface.)
On the other hand, if the semantics are such that they can be defined in terms of other methods in the interface, and implementers of the interface will just tend to write the same code over and over again, then it's better to make a utility method that takes an instance of the interface as an argument.
They are utility methods and not core List functionality. The List interface would just get bloated if you added every possible operation you could do on a List. And the operations in Collections do not need to know about the internals of a List, they operate on the public interface so can happily live in an external class.
There are two explanations here:
Historical: Collections class was created after List interface. Designers chose to preserve backward compatibility of already existing interface. Otherwise a lot of developers would have to change their code.
Logical: The methods you are talking about do not require internal knowledge on List implementation and can be implemented over ANY collection implementing it.

Categories