Retrofit/Gson how to create type adapters dynamically - kotlin

I learned from one example, so I am not sure if this is the optimal way or not, but anyways, I use the following code. I create one Retrofit instance and use it for all requests.
Since there are many methods, there are many types of data. It seems that I can create adapters (json -> my data class) automatically simply by adding annotations. But I needed more control (inheritance: the data classes have shared fields, dependency: some fields may not exist depending on other field's values), so I created a custom adaptor for each of the classes. So, currently my code is like this:
if (instance == null)
{
val gson = GsonBuilder()
.registerTypeAdapter(myClass1::class.java, myClassDeserialiser1())
.... (tens of this) ....
.registerTypeAdapter(myClass30::class.java, myClassDeserialiser30())
.create()
instance = Retrofit.Builder().
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(MyAPIs::class.java);
}
return instance
The problem above is that I am creating instances of all parsers at the same time in advance. This may be inefficient. I wish I could create them when they are first needed. Is that possible?

You can add a #JsonAdapter annotation to your class definition in lieu of calling registerTypeAdapter. I can't comment on its efficiency, but it keeps the adapter info tied to the object instead of the creation of your Gson object, which sounds like what you want.

Related

Where should the code processing the state of the object be?

I have a class as follows:
data class ProductState(
val id: Int,
val products: MutableMap<Int, MutableSet<Int>> = mutableMapOf(),
val customerTopics: Topic = Topic()
)
It is basically a data class.
Now I have a function that among other things, processes the products and customerTopics and creates some output based on the processing.
But it seems to me that it is not a good idea to have the logic in the function.
My question is:
Do we create methods inside the data class for the processing of the object'state? If so would it be some companion object? Or is there some other design pattern that deals with this better?
In kotlin you have several options:
Additional method on the data class (if it should be called in multiple other places);
Public extension method in the same file as the data class (if it should be called in multiple other places but you want to keep your data class simple and have the handling methods separated);
Private extension method in the same file as the only place where it is called (this only applies if this processing is to be called in a single place in your code);
Private method in the only place where this processing is needed.
The best place really depends on what the processing is (is it very specific to ProductState or does it need additional data? If it is very specific then it may make sense to keep it as a ProductState method or an extension function) and in how many places it will be triggered (if in a single very specific place, then maybe keeping it along-side that piece of code as a private extension function or private method might be the best option).

Serialize list of objects with json_serializable without creating extra class

I saw a tutorial where an extra class is created just to be able to serialize a list of objects, instead of a single object:
I'm using json_serializable to generate some serialization code for my class Preference, but now I want to save a list of preferences using shared_preferences and I get an error obviously.
var sSavedPrefs = json.encode(PreferenceRepo.getSavedPrefs());
prefs.setString(saved_prefs_key, sSavedPrefs );
I used
#JsonSerializable()
class Preference{...}
to make it serializable, but I don't want to create an extra class like
#JsonSerializable()
class Preferences{...}
just to make it work - is there a better way?
I found a way:
Using the setStringList method I could create a List where I added each serialized object one by one without needing an extra list class. I also noticed that json.encode might not have been the right method to use, I saw jsonEncode in another tutorial and used it instead:
List<String> savedPrefsJson = [];
for (Preference savedPref in PreferenceRepo.savedPrefs) {
String savedPrefJson = jsonEncode(savedPref);
savedPrefsJson.add(savedPrefJson);
}
prefs.setStringList(saved_prefs_key, savedPrefsJson);

Accessing properties of a Kotlin entity

I'm new to Kotlin, so apologies if I'm not articulating concepts correctly. I have an instance of an Entity
[TestEntity(applicationId=1, timestamp=2018-01-24T18:40:30, issueState=MA, product=test, status=sold, paymentMode=VISA, premium=null)]
I am writing a service that is going to take these keys and use them to create the headers of a report. The keys may change depending on the type of report the user is trying to generate, which will have an impact on the Entity that will be instantiated.
I want to be able to iterate over this Entity so that I can create an array to use for the headers. Any thoughts on how I do this?
I think the cleanest solution is storing values in a map and delegating properties to it.
Don't think you can otherwise iterate over class fields without some verbose getter chain or ugly reflection shenanigans.
For example here you can access map fields as if they were class fields, but can also easily iterate over map.
data class TestEntity(val map : Map<String, Any>){
val appId : Int by map
val timeStamp : Long by map
(... more fields)
}

Are serializers the right spot to remove shared state from Akka messages?

I am working on a distributed algorithm and decided to use a Akka to scale it across machines. The machines need to exchange messages very frequently and these messages reference some immutable objects that exist on every machine. Hence, it seems sensible to "compress" the messages in the sense that the shared, replicated objects should not be serialized in the messages. Not only would this save on network bandwidth but it also would avoid creating duplicate objects in the receiver side whenever a message is deserialized.
Now, my question is how to do this properly. So far, I could think of two options:
Handle this on the "business layer", i.e., converting my original message objects to some reference objects that replace references to the shared, replicated objects by some symbolic references. Then, I would send those reference objects rather than the original messages. Think of it as replacing some actual web resource with a URL. Doing this seems rather straight-forward in terms of coding but it also drags serialization concerns into the actual business logic.
Write custom serializers that are aware of the shared, replicated objects. In my case, it would be okay that this solution would introduce the replicated, shared objects as global state to the actor systems via the serializers. However, the Akka documentation does not describe how to programmatically add custom serializers, which would be necessary to weave in the shared objects with the serializer. Also, I could imagine that there are a couple of reasons, why such a solution would be discouraged. So, I am asking here.
Thanks a lot!
It's possible to write your own, custom serializers and let them do all sorts of weird things, then you can bind them at the config level as usual:
class MyOwnSerializer extends Serializer {
// If you need logging here, introduce a constructor that takes an ExtendedActorSystem.
// class MyOwnSerializer(actorSystem: ExtendedActorSystem) extends Serializer
// Get a logger using:
// private val logger = Logging(actorSystem, this)
// This is whether "fromBinary" requires a "clazz" or not
def includeManifest: Boolean = true
// Pick a unique identifier for your Serializer,
// you've got a couple of billions to choose from,
// 0 - 40 is reserved by Akka itself
def identifier = 1234567
// "toBinary" serializes the given object to an Array of Bytes
def toBinary(obj: AnyRef): Array[Byte] = {
// Put the code that serializes the object here
//#...
Array[Byte]()
//#...
}
// "fromBinary" deserializes the given array,
// using the type hint (if any, see "includeManifest" above)
def fromBinary(
bytes: Array[Byte],
clazz: Option[Class[_]]): AnyRef = {
// Put your code that deserializes here
//#...
null
//#...
}
}
But this raises an important question: if your messages all references data that is shared on the machines already, why would you want to put in the message the pointer to the object (very bad! messages should be immutable, and a pointer isn't!), rather than some sort of immutable, string objectId (kinda your option 1) ? This is a much better option when it comes to preserving the immutability of the messages, and there is little change in your business logic (just put a wrapper over the shared state storage)
for more info, see the documentation
I finally went with the solution proposed by Diego and want to share some more details on my reasoning and solution.
First of all, I am also in favor of option 1 (handling the "compaction" of messages in the business layer) for those reasons:
Serializers are global to the actor system. Making them stateful is actually a most severe violation of Akka's very philosophy as it goes against the encapsulation of behavior and state in actors.
Serializers have to be created upfront, anyway (even when adding them "programatically").
Design-wise, one can argue that "message compaction is not a responsibility of the serializer, either. In a strict sense, serialization is merely the transformation of runtime-specific data into a compact, exchangable representation. Changing what to serialize, is not a task of a serializer, though.
Having settled upon this, I still strived for a clear separation of "message compaction" and the actual business logic in the actors. I came up with a neat way to do this in Scala, which I want to share here. The basic idea is to make the message itself look like a normal case class but still allow these messages to "compactify" themselves. Here is an abstract example:
class Sender extends ActorRef {
def context: SharedContext = ... // This is the shared data present on every node.
// ...
def someBusinessLogic(receiver: ActorRef) {
val someData = computeData
receiver ! MyMessage(someData)
}
}
class Receiver extends ActorRef {
implicit def context: SharedContext = ... // This is the shared data present on every node.
def receiver = {
case MyMessage(someData) =>
// ...
}
}
object Receiver {
object MyMessage {
def apply(someData: SomeData) = MyCompactMessage(someData: SomeData)
def unapply(myCompactMessage: MyCompactMessage)(implicit context: SharedContext)
: Option[SomeData] =
Some(myCompactMessage.someData(context))
}
}
As you can see, the sender and receiver code feels just like using a case class and in fact, MyMessage could be a case class.
However, by implementing apply and unapply manually, one can insert its own "compactification" logic and also implicitly inject the shared data necessary to do the "uncompactification", without touching the sender and receiver. For defining MyCompactMessage, I found Protocol Buffers to be especially suited, as it is already a dependency of Akka and efficient in terms of space and computation, but any other solution would do.

God object - decrease coupling to a 'master' object

I have an object called Parameters that gets tossed from method to method down and up the call tree, across package boundaries. It has about fifty state variables. Each method might use one or two variables to control its output.
I think this is a bad idea, beacuse I can't easily see what a method needs to function, or even what might happen if with a certain combination of parameters for module Y which is totally unrelated to my current module.
What are some good techniques for decreasing coupling to this god object, or ideally eliminating it ?
public void ExporterExcelParFonds(ParametresExecution parametres)
{
ApplicationExcel appExcel = null;
LogTool.Instance.ExceptionSoulevee = false;
bool inclureReferences = parametres.inclureReferences;
bool inclureBornes = parametres.inclureBornes;
DateTime dateDebut = parametres.date;
DateTime dateFin = parametres.dateFin;
try
{
LogTool.Instance.AfficherMessage(Variables.msg_GenerationRapportPortefeuilleReference);
bool fichiersPreparesAvecSucces = PreparerFichiers(parametres, Sections.exportExcelParFonds);
if (!fichiersPreparesAvecSucces)
{
parametres.afficherRapportApresGeneration = false;
LogTool.Instance.ExceptionSoulevee = true;
}
else
{
The caller would do :
PortefeuillesReference pr = new PortefeuillesReference();
pr.ExporterExcelParFonds(parametres);
First, at the risk of stating the obvious: pass the parameters which are used by the methods, rather than the god object.
This, however, might lead to some methods needing huge amounts of parameters because they call other methods, which call other methods in turn, etcetera. That was probably the inspiration for putting everything in a god object. I'll give a simplified example of such a method with too many parameters; you'll have to imagine that "too many" == 3 here :-)
public void PrintFilteredReport(
Data data, FilterCriteria criteria, ReportFormat format)
{
var filteredData = Filter(data, criteria);
PrintReport(filteredData, format);
}
So the question is, how can we reduce the amount of parameters without resorting to a god object? The answer is to get rid of procedural programming and make good use of object oriented design. Objects can use each other without needing to know the parameters that were used to initialize their collaborators:
// dataFilter service object only needs to know the criteria
var dataFilter = new DataFilter(criteria);
// report printer service object only needs to know the format
var reportPrinter = new ReportPrinter(format);
// filteredReportPrinter service object is initialized with a
// dataFilter and a reportPrinter service, but it doesn't need
// to know which parameters those are using to do their job
var filteredReportPrinter = new FilteredReportPrinter(dataFilter, reportPrinter);
Now the FilteredReportPrinter.Print method can be implemented with only one parameter:
public void Print(data)
{
var filteredData = this.dataFilter.Filter(data);
this.reportPrinter.Print(filteredData);
}
Incidentally, this sort of separation of concerns and dependency injection is good for more than just eliminating parameters. If you access collaborator objects through interfaces, then that makes your class
very flexible: you can set up FilteredReportPrinter with any filter/printer implementation you can imagine
very testable: you can pass in mock collaborators with canned responses and verify that they were used correctly in a unit test
If all your methods are using the same Parameters class then maybe it should be a member variable of a class with the relevant methods in it, then you can pass Parameters into the constructor of this class, assign it to a member variable and all your methods can use it with having to pass it as a parameter.
A good way to start refactoring this god class is by splitting it up into smaller pieces. Find groups of properties that are related and break them out into their own class.
You can then revisit the methods that depend on Parameters and see if you can replace it with one of the smaller classes you created.
Hard to give a good solution without some code samples and real world situations.
It sounds like you are not applying object-oriented (OO) principles in your design. Since you mention the word "object" I presume you are working within some sort of OO paradigm. I recommend you convert your "call tree" into objects that model the problem you are solving. A "god object" is definitely something to avoid. I think you may be missing something fundamental... If you post some code examples I may be able to answer in more detail.
Query each client for their required parameters and inject them?
Example: each "object" that requires "parameters" is a "Client". Each "Client" exposes an interface through which a "Configuration Agent" queries the Client for its required parameters. The Configuration Agent then "injects" the parameters (and only those required by a Client).
For the parameters that dictate behavior, one can instantiate an object that exhibits the configured behavior. Then client classes simply use the instantiated object - neither the client nor the service have to know what the value of the parameter is. For instance for a parameter that tells where to read data from, have the FlatFileReader, XMLFileReader and DatabaseReader all inherit the same base class (or implement the same interface). Instantiate one of them base on the value of the parameter, then clients of the reader class just ask for data to the instantiated reader object without knowing if the data come from a file or from the DB.
To start you can break your big ParametresExecution class into several classes, one per package, which only hold the parameters for the package.
Another direction could be to pass the ParametresExecution object at construction time. You won't have to pass it around at every function call.
(I am assuming this is within a Java or .NET environment) Convert the class into a singleton. Add a static method called "getInstance()" or something similar to call to get the name-value bundle (and stop "tramping" it around -- see Ch. 10 of "Code Complete" book).
Now the hard part. Presumably, this is within a web app or some other non batch/single-thread environment. So, to get access to the right instance when the object is not really a true singleton, you have to hide selection logic inside of the static accessor.
In java, you can set up a "thread local" reference, and initialize it when each request or sub-task starts. Then, code the accessor in terms of that thread-local. I don't know if something analogous exists in .NET, but you can always fake it with a Dictionary (Hash, Map) which uses the current thread instance as the key.
It's a start... (there's always decomposition of the blob itself, but I built a framework that has a very similar semi-global value-store within it)