how to exclude particular class from keep class tag proguard - proguard

I have multiple classes in one package. I am keeping all these classes with a single rule
-keep class com.something.folder.** { *; }.
How can I obfuscate one particular class from that package?

You can use an exclusion pattern like this:
-keep class !com.example.A,com.example.** { *; }
This will keep all classes in the package com.example and sub-packages, except for class com.example.A.
ProGuard will analyze the provided patterns in sequential order, and stop if it encounters a matching one. Thus you need to make sure that the exclusion pattern comes first.

Related

Defining classes with several API versions together

That's not apparently possible...
role Versioned {
method version () {
return self.^api;
}
}
class WithApi:ver<0.0.1>:auth<github:JJ>:api<0> does Versioned {}
class WithApi:ver<0.0.1>:auth<github:JJ>:api<1> does Versioned {}
say WithApi:api<0>.new.version;
say WithApi:api<1>.new.version;
This dies with
==SORRY!=== Error while compiling /home/jmerelo/progs/perl6/my-perl6-examples/api-versioned.p6
Redeclaration of symbol 'WithApi'
at /home/jmerelo/progs/perl6/my-perl6-examples/api-versioned.p6:11
------> 1>:auth<github:JJ>:api<1> does Versioned⏏ {}
So is it even possible to use classes with different apis, same name in a single program?
Update: if they are included in different files, this is the error obtained:
P6M Merging GLOBAL symbols failed: duplicate definition of symbol WrongType
Two things are creating a problem in this example:
class is by default our, which causes a name clash
the short name of the class is the same in the outer namespace, causing a clash
If we adapt the code slightly:
role Versioned {
method version () {
return self.^api;
}
}
my constant one = my class WithApi:ver<0.0.1>:auth<github:JJ>:api<1> does Versioned {}
my constant two = my class WithApi:ver<0.0.1>:auth<github:JJ>:api<2> does Versioned {}
say one.version; # 1
say two.version; # 2
I did find that there is a bug for :api<0>. Apparently this is considered to be equivalent to no :api setting, resulting in an empty string rather than 0.

What are sealed classes in Kotlin?

I'm a beginner in Kotlin and recently read about Sealed Classes. But from the doc the only think I actually get is that they are exist.
The doc stated, that they are "representing restricted class hierarchies". Besides that I found a statement that they are enums with superpower. Both aspects are actually not clear.
So can you help me with the following questions:
What are sealed classes and what is the idiomatic way of using ones?
Does such a concept present in other languages like Python, Groovy or C#?
UPDATE:
I carefully checked this blog post and still can't wrap my head around that concept. As stated in the post
Benefit
The feature allows us to define class hierarchies that are
restricted in their types, i.e. subclasses. Since all subclasses need
to be defined inside the file of the sealed class, there’s no chance
of unknown subclasses which the compiler doesn’t know about.
Why the compiler doesn't know about other subclasses defined in other files? Even IDE knows that. Just press Ctrl+Alt+B in IDEA on, for instance, List<> definition and all implementations will be shown even in other source files. If a subclass can be defined in some third-party framework, which not used in the application, why should we care about that?
Say you have a domain (your pets) where you know there is a definite enumeration (count) of types. For example, you have two and only two pets (which you will model with a class called MyPet). Meowsi is your cat and Fido is your dog.
Compare the following two implementations of that contrived example:
sealed class MyPet
class Meowsi : MyPet()
class Fido : MyPet()
Because you have used sealed classes, when you need to perform an action depending on the type of pet, then the possibilities of MyPet are exhausted in two and you can ascertain that the MyPet instance will be exactly one of the two options:
fun feed(myPet: MyPet): String {
return when(myPet) {
is Meowsi -> "Giving cat food to Meowsi!"
is Fido -> "Giving dog biscuit to Fido!"
}
}
If you don't use sealed classes, the possibilities are not exhausted in two and you need to include an else statement:
open class MyPet
class Meowsi : MyPet()
class Fido : MyPet()
fun feed(myPet: MyPet): String {
return when(myPet) {
is Mewosi -> "Giving cat food to Meowsi!"
is Fido -> "Giving dog biscuit to Fido!"
else -> "Giving food to someone else!" //else statement required or compiler error here
}
}
In other words, without sealed classes there is not exhaustion (complete coverage) of possibility.
Note that you could achieve exhaustion of possiblity with Java enum however these are not fully-fledged classes. For example, enum cannot be subclasses of another class, only implement an interface (thanks EpicPandaForce).
What is the use case for complete exhaustion of possibilities? To give an analogy, imagine you are on a tight budget and your feed is very precious and you want to ensure you don't end up feeding extra pets that are not part of your household.
Without the sealed class, someone else in your home/application could define a new MyPet:
class TweetiePie : MyPet() //a bird
And this unwanted pet would be fed by your feed method as it is included in the else statement:
else -> "Giving food to someone else!" //feeds any other subclass of MyPet including TweetiePie!
Likewise, in your program exhaustion of possibility is desirable because it reduces the number of states your application can be in and reduces the possibility of bugs occurring where you have a possible state where behaviour is poorly defined.
Hence the need for sealed classes.
Mandatory else
Note that you only get the mandatory else statement if when is used as an expression. As per the docs:
If [when] is used as an expression, the value of the satisfied branch becomes the value of the overall expression [... and] the else branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions
This means you won't get the benefit of sealed classes for something like this):
fun feed(myPet: MyPet): Unit {
when(myPet) {
is Meowsi -> println("Giving cat food to Meowsi!") // not an expression so we can forget about Fido
}
}
To get exhaustion for this scenario, you would need to turn the statement into an expression with return type.
Some have suggested an extension function like this would help:
val <T> T.exhaustive: T
get() = this
Then you can do:
fun feed(myPet: MyPet): Unit {
when(myPet) {
is Meowsi -> println("Giving cat food to Meowsi!")
}.exhaustive // compiler error because we forgot about Fido
}
Others have suggested that an extension function pollutes the namespace and other workarounds (like compiler plugins) are required.
See here for more about this problem.
Sealed classes are easier to understand when you understand the kinds of problems they aim to solve. First I'll explain the problems, then I'll introduce the class hierarchies and the restricted class hierarchies step by step.
We'll take a simple example of an online delivery service where we use three possible states Preparing, Dispatched and Delivered to display the current status of an online order.
Problems
Tagged class
Here we use a single class for all the states. Enums are used as type markers. They are used for tagging the states Preparing, Dispatched and Delivered :
class DeliveryStatus(
val type: Type,
val trackingId: String? = null,
val receiversName: String? = null) {
enum class Type { PREPARING, DISPATCHED, DELIVERED }
}
The following function checks the state of the currently passed object with the help of enums and displays the respective status:
fun displayStatus(state: DeliveryStatus) = when (state.type) {
PREPARING -> print("Preparing for dispatch")
DISPATCHED -> print("Dispatched. Tracking ID: ${state.trackingId ?: "unavailable"}")
DELIVERED -> print("Delivered. Receiver's name: ${state.receiversName ?: "unavailable"}")
}
As you can see, we are able to display the different states properly. We also get to use exhaustive when expression, thanks to enums. But there are various problems with this pattern:
Multiple responsibilities
The class DeliveryStatus has multiple responsibilities of representing different states. So it can grow bigger, if we add more functions and properties for different states.
More properties than needed
An object has more properties than it actually needs in a particular state. For example, in the function above, we don't need any property for representing the Preparing state. The trackingId property is used only for the Dispatched state and the receiversName property is concerned only with the Delivered state. The same is true for functions. I haven't shown functions associated with states to keep the example small.
No guarantee of consistency
Since these unused properties can be set from unrelated states, it's hard to guarantee the consistency of a particular state. For example, one can set the receiversName property on the Preparing state. In that case, the Preparing will be an illegal state, because we can't have a receiver's name for the shipment that hasn't been delivered yet.
Need to handle null values
Since not all properties are used for all states, we have to keep the properties nullable. This means we also need to check for the nullability. In the displayStatus() function we check the nullability using the ?:(elvis) operator and show unavailable, if that property is null. This complicates our code and reduces readability. Also, due to the possibility of a nullable value, the guarantee for consistency is reduced further, because the null value of receiversName in Delivered is an illegal state.
Introducing Class Hierarchies
Unrestricted class hierarchy: abstract class
Instead of managing all the states in a single class, we separate the states in different classes. We create a class hierarchy from an abstract class so that we can use polymorphism in our displayStatus() function:
abstract class DeliveryStatus
object Preparing : DeliveryStatus()
class Dispatched(val trackingId: String) : DeliveryStatus()
class Delivered(val receiversName: String) : DeliveryStatus()
The trackingId is now only associated with the Dispatched state and receiversName is only associated with the Delivered state. This solves the problems of multiple responsibilities, unused properties, lack of state consistency and null values.
Our displayStatus() function now looks like the following:
fun displayStatus(state: DeliveryStatus) = when (state) {
is Preparing -> print("Preparing for dispatch")
is Dispatched -> print("Dispatched. Tracking ID: ${state.trackingId}")
is Delivered -> print("Delivered. Received by ${state.receiversName}")
else -> throw IllegalStateException("Unexpected state passed to the function.")
}
Since we got rid of null values, we can be sure that our properties will always have some values. So now we don't need to check for null values using the ?:(elvis) operator. This improves code readability.
So we solved all the problems mentioned in the tagged class section by introducing a class hierarchy. But the unrestricted class hierarchies have the following shortcomings:
Unrestricted Polymorphism
By unrestricted polymorphism I mean that our function displayStatus() can be passed a value of unlimited number of subclasses of the DeliveryStatus. This means we have to take care of the unexpected states in displayStatus(). For this, we throw an exception.
Need for the else branch
Due to unrestricted polymorphism, we need an else branch to decide what to do when an unexpected state is passed. If we use some default state instead of throwing an exception and then forget to take care of any newly added subclass, then that default state will be displayed instead of the state of the newly created subclass.
No exhaustive when expression
Since the subclasses of an abstract class can exist in different packages and compilation units, the compiler doesn't know all the possible subclasses of the abstract class. So it won't flag an error at compile time, if we forget to take care of any newly created subclasses in the when expression. In that case, only throwing an exception can help us. Unfortunately, we'll know about the newly created state only after the program crashes at runtime.
Sealed Classes to the Rescue
Restricted class hierarchy: sealed class
Using the sealed modifier on a class does two things:
It makes that class an abstract class. Since Kotlin 1.5, you can use a sealed interface too.
It makes it impossible to extend that class outside of that file. Since Kotlin 1.5 the same file restriction has been removed. Now the class can be extended in other files too but they need to be in the same compilation unit and in the same package as the sealed type.
sealed class DeliveryStatus
object Preparing : DeliveryStatus()
class Dispatched(val trackingId: String) : DeliveryStatus()
class Delivered(val receiversName: String) : DeliveryStatus()
Our displayStatus() function now looks cleaner:
fun displayStatus(state: DeliveryStatus) = when (state) {
is Preparing -> print("Preparing for Dispatch")
is Dispatched -> print("Dispatched. Tracking ID: ${state.trackingId}")
is Delivered -> print("Delivered. Received by ${state.receiversName}")
}
Sealed classes offer the following advantages:
Restricted Polymorphism
By passing an object of a sealed class to a function, you are also sealing that function, in a sense. For example, now our displayStatus() function is sealed to the limited forms of the state object, that is, it will either take Preparing, Dispatched or Delivered. Earlier it was able to take any subclass of DeliveryStatus. The sealed modifier has put a limit on polymorphism. As a result, we don't need to throw an exception from the displayStatus() function.
No need for the else branch
Due to restricted polymorphism, we don't need to worry about other possible subclasses of DeliveryStatus and throw an exception when our function receives an unexpected type. As a result, we don't need an else branch in the when expression.
Exhaustive when expression
Just like all the possible values of an enum class are contained inside the same class, all the possible subtypes of a sealed class are contained inside the same package and the same compilation unit. So, the compiler knows all the possible subclasses of this sealed class. This helps the compiler to make sure that we have covered(exhausted) all the possible subtypes in the when expression. And when we add a new subclass and forget to cover it in the when expression, it flags an error at compile time.
Note that in the latest Kotlin versions, your when is exhaustive for the when expressions as well the when statements.
Why in the same file?
The same file restriction has been removed since Kotlin 1.5. Now you can define the subclasses of the sealed class in different files but the files need to be in the same package and the same compilation unit. Before 1.5, the reason that all the subclasses of a sealed class needed to be in the same file was that it had to be compiled together with all of its subclasses for it to have a closed set of types. If the subclasses were allowed in other files, the build tools like Gradle would have to keep track of the relations of files and this would affect the performance of incremental compilation.
IDE feature: Add remaining branches
When you just type when (status) { } and press Alt + Enter, Enter, the IDE automatically generates all the possible branches for you like the following:
when (state) {
is Preparing -> TODO()
is Dispatched -> TODO()
is Delivered -> TODO()
}
In our small example there are just three branches but in a real project you could have hundreds of branches. So you save the effort of manually looking up which subclasses you have defined in different files and writing them in the when expression one by one in another file. Just use this IDE feature. Only the sealed modifier enables this.
That's it! Hope this helps you understand the essence of sealed classes.
If you've ever used an enum with an abstract method just so that you could do something like this:
public enum ResultTypes implements ResultServiceHolder {
RESULT_TYPE_ONE {
#Override
public ResultOneService getService() {
return serviceInitializer.getResultOneService();
}
},
RESULT_TYPE_TWO {
#Override
public ResultTwoService getService() {
return serviceInitializer.getResultTwoService();
}
},
RESULT_TYPE_THREE {
#Override
public ResultThreeService getService() {
return serviceInitializer.getResultThreeService();
}
};
When in reality what you wanted is this:
val service = when(resultType) {
RESULT_TYPE_ONE -> resultOneService,
RESULT_TYPE_TWO -> resultTwoService,
RESULT_TYPE_THREE -> resultThreeService
}
And you only made it an enum abstract method to receive compile time guarantee that you always handle this assignment in case a new enum type is added; then you'll love sealed classes because sealed classes used in assignments like that when statement receive a "when should be exhaustive" compilation error which forces you to handle all cases instead of accidentally only some of them.
So now you cannot end up with something like:
switch(...) {
case ...:
...
default:
throw new IllegalArgumentException("Unknown type: " + enum.name());
}
Also, enums cannot extend classes, only interfaces; while sealed classes can inherit fields from a base class. You can also create multiple instances of them (and you can technically use object if you need the subclass of the sealed class to be a singleton).

How to prevent kotlin.Unit object from being stripped by Proguard

Proguard stripes kotlin.Unit standalone object (in Kotlin runtime library), and that causes a compilation error if you are using this type. The following rule does not help with keeping this element (perhaps because Unit is not a class, it's an object):
-keep class kotlin.Unit.** { *; }
We use the Unit type like this:
fun assert(func : Assert.() -> Unit) = Assert().apply(func)
Is there a workaround for this issue or am I missing something?
In Progaurd rules, wildcards after the name of the class indicate nested classes. So get rid of the .** after Kotlin.Unit:
-keep class kotlin.Unit { *; }
Not directly relevant but if you use Kotlin's collections, you need to add the following Proguard rule as well:
-keep class kotlin.collections.CollectionsKt { *; }
Since Kotlin's Standard Library has its own Collections file and it contains top level functions and because files with top-level functions are not a direct Java class, you should use the name Kotlin conventionally uses to store this file as a Java class. From Kotlin's documentation:
All the functions and properties declared in a file example.kt inside
a package org.foo.bar are put into a Java class named
org.foo.bar.ExampleKt.
The name of the generated Java class can be changed using the #JvmName
annotation.
And again don't use the .** wildcard after the class name here.

how does EBean map classes to tables?

How does EBean map classes to tables?
I have tables like "expense_details" and classes like model.ExpenseDetails, for example, and the classes just use the #Entity annotation without explicit mapping to a table.
Is the mapping done automatically by EBean (is it smart enough with all those "_" and CamelCase names)?
Yes it is, it uses exactly rule that you described, for SomeModel model it looks for some_model table, of course you can override it ie. using #Table annotation like:
#Entity
#Table(name = "my_custom_table_name")
public class SomeModel extends Model {
...
}

Is there a common name for this code smell?

I refer to it as the "delivery boy". I've seen several variants of it but the issue is that a class has dependency for the sole purpose of passing it on to collaborators and never using the dependency itself.
(I'm using PHP because it's what I'm most familiar with but this is language agnostic)
class Dependency{}
class B {
public function setDependency(Dependency $dependency) {
//...
}
}
class A {
private $b;
private $dependency;
public function __construct(Dependency $dependency, B $b) {
$this->dependency = $dependency;
$this->b = $b;
}
public function foo() {
$this->b->setDependency($this->dependency);
}
}
Probably the most common variant I see in the wild is abusing inheritance for this purpose, having a property in the parent class which exists so that the child classes have access to the dependency even if the parent class never actually uses the dependency itself.
class Dependency{}
class A {
protected $dependency;
public function __construct(Dependency $dependency) {
$this->dependency = $dependency;
}
}
class B extends A {
public function foo() {
$this->dependency->bar();
}
}
I see this in code far more than I'd like and it doesn't make me very happy! I just wondered if there was a name for this so that I can link people to reading materials on why it's a bad idea. As it stands, I don't know what to search for!
I'm not aware of any name, but I kind of like Delivery boy... though I suppose some might consider the name borderline offensive.
Typically this problem is solved with either Dependency Injection or a Service Locator, although way too many people use Singleton for this (inappropriately).
I'm not familiar enough with PHP to know if PHP offers a real DI solution (as opposed to poor man's DI), but I think a service locator would be acceptable if there isn't (even though service locator is often a code smell in itself).
The problem related to inheritance in the second snippet looks like to me "Broken Hierarchy". This smell occurs when the base class and its derived class do not share an IS-A relationship. It is very common to find code that uses inheritance just for convenience (for reuse) and not because it makes sense to have a hierarchy where the participating classes are are related (by IS-A relationship).
(I borrowed the smell terminology (i.e. Broken Hierarchy) from the book "Refactoring for software design smells")