Giter Site home page Giter Site logo

programmerr47 / ganalytics Goto Github PK

View Code? Open in Web Editor NEW
11.0 2.0 4.0 239 KB

Analytics library preferably sharpened for Google Analytics

License: MIT License

Kotlin 97.58% Java 2.42%
analytics annotations google-analytics analytics-tracking analytics-api

ganalytics's People

Contributors

programmerr47 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ganalytics's Issues

Add @Action annotation

Suggested behavior:

  • can be used only on a method

The description is self-explanatory. If a method doesn't have this annotation, then its name is action

Added supporting of Properties in Group-Interfaces

We need to add supporting of val properties in group analytics interface. Thus, the group interface will look like:

interface AnalyticsGroup {
    val single: AnalyticsSingle
}

instead of

interface AnalyticsGroup {
    fun single(): AnalyticsSingle
}

And usage will be like analyticsGroup.single instead of analyticsGroup.single()
Thus, we will eliminate unnecessary brackets

Increase scope annotation for Group interfaces

Currently, we have AnalyticsGroupWrapper as interface of all analytics interfaces, but it contains no annotation. I think it will be usefull if we could use next list of annotation on methods (equals to use these annotations on concrete analytics interface):

  • @Category
  • @HasPrefix / @NoPrefix
  • @Convention

Also, it would be great to apply several annotations on main group interface:

  • @HasPrefix / @NoPrefix
  • @Convention

Add annotation for merging method name and class name in action name

We need to add annotation that will allow to combine interface name and method name to one action name. For example:

interface Sample {
    @DesiredAnnotation fun action()
}

will give category = sample and action = sampleaction

Also, need to think about splitters. For example, to generate action = sample-action or action = sample_action

Suggested names for annotation are: @short, @Prefix, @WithPrefix, @HasPrefix
Suggested parameters:
name - specify prefix name (default is name of class in lower case)
splitter - specify splitter string (default is nothing)

Suggested behavior:

  • can be used on interface and method
  • class annotation gives behavior to all methods of this interface
  • if we have annotation on interface and same annotation on method, then method annotation wins

Add Default Labels

We need to think, do we really need default labels or not. And if answer is yes, we need to think, how we will implement it.

There is several ways to implement:

  1. Introduce new annotation @DefLabel or @LabelDef that will be used only for methods. It will has a parameter name with specified label string.
  2. Increase functionality of @Action annotation and defLabels parameter.

Maybe there are other considerable ways, but currently only two are accepted.

Why?:

There are cases, when analytic with same category and action has 2 or 3 different labels.
For example: _category_= quiz, _action_= send, _label_= question/answer
In current implementation we can create an enum with two variants:

enum class QuizSendLabel {
    QUIESTION, ANSWER
}

And then pass it as a parameter of appropriate method:

interface AnalyticsQuiz {
    fun send(label: QuizSendLabel)
}

But maybe in such cases it is more interesting to write something like:

interface AnalyticsQuiz {
    @Action("send") @DefLabel("question") fun question()
    @Action("send") @DefLabel("answer") fun answer()
}

It seems that result takes up more space, but we eliminate one enum class with two additional instances. So it can be more important for space critical apps.

Also, with second proposed approach in the beginning of issue it will look like:

interface AnalyticsQuiz {
    @Action(name = "send", defLabel = "question") fun question()
    @Action(name = "send", defLabel = "answer") fun answer()
}

Which gives us possibility to not use redundant annotation, but takes up even more space.

P.S.: There is 3rd less obvious solutions: annotation @LabelFun with parameter action
which will turn name of the method to label name and action is needed to be defined as a parameter, by user of library:

interface AnalyticsQuiz {
    @LabelFun("send") fun question()
    @LabelFun("send") fun answer()
}

So it will take small space, but we will eliminate redundant objects and enum.
Also, it will have additional second parameter label for explicit defining a label.

Added caching mechanism

Currently, when AnanlyticsGroupWrapper is used, for each method invocation new instance of AnalyticsSingleWrapper is created.

Next aim is to cache single wrappers to be able to reuse previous created instances for new methods with same setups and for old methods that will be invoked periodically.

Add @Label annotation

Need to add @Label annotation. Currently, it will be parameterless (but then we will add strategies and e.t.c.) I think we need to implement next rules or similar to them (in order to write less code):

These rules are for parameters without @Label annotation:

  • if there is only one parameter in a method, then it is a label. Thus we need to convert it to String (if it isn't a string already)
  • if there are two parameters and one of them is String, and another is Long or Int, then first will be a label, and last will be a value (I will not implement it now but for the future)
  • if there are two parameters and one of them is String, then it is considered as a label, and other we need to convert to long
  • if there are two parameters and one of them is Long or Int, then it is considered as a value, and other we need to convert to String
  • if there are more than two parameters, then there will be a runtime exception.

Rules for @Label annotation:

  • if there are two values and one of them marked as @Label, then we need to convert somehow other to value
  • if there are more than two parameters, then regardless to annotation we need to throw an exception

Enhance DefaultLabelConverter for Enums

May be it will be good to enhance default label converter for some types.
In this case for enums by default the name will be taken and converted by chosen namingConvention

Add LabelConverter for Category Interface

As it appeared, there are cases, when many methods in interface use the same LabelConverter. In that case, a lot of duplicates appeared:

@HasPrefix
interface AnalyticsCar {
    fun sell(@Label(AdvertConverter::class) car: Car)
    fun buy(@Label(AdvertConverter::class) car: Car)
    fun review(@Label(AdvertConverter::class) car: Car)
    fun check(@Label(AdvertConverter::class) car: Car)
    fun utilize(@Label(AdvertConverter::class) car: Car)

    object CarConverter : TypedLabelConverter<Car> {
        override fun convertTyped(label: Car) =
                if (car.isBeauty()) "cool car"
                else if (car.isUgly()) "not so cool car"
                else "normal car"
    }
}

It seems that in that way we can add a global converter to GanalyticsSettings. But in other interfaces, we can have other converters for Car. That's why we need to think about the scope of the @Label annotation or introduce a @LabelConverter annotation.

In second case (which is preferable) we need to think how to pass several converters: each for each type of parameters.

As the result of aforementioned example we will have:

@HasPrefix
@LabelConverter(AdvertConverter::class)
interface AnalyticsCar {
    fun sell(car: Car)
    fun buy(car: Car)
    fun review(car: Car)
    fun check(car: Car)
    fun utilize(car: Car)

    object CarConverter : TypedLabelConverter<Car> {
        override fun convertTyped(label: Car) =
                if (car.isBeauty()) "cool car"
                else if (car.isUgly()) "not so cool car"
                else "normal car"
    }
}

Add @Category annotation

Suggested behavior:

  • can be used on interface or method
  • interface annotation gives behavior to all its methods
  • method annotation wins over interface annotation

The description is self-explanatory. If we have no this annotation, the name of interface is category. Annotation without parameter is redundant and thus useless.

Add LabelInterfaces

In case when we have an action method in Category Interface with enumeration of labels, we need to create special enum for it, if there are no other options. I think, it will be better to provide special LabelInterface. So for example, this:

interface AnalyticsPerson {
    fun live(type: LiveTypeLabel)
}

enum class LiveTypeLabel { FLAT, HOUSE, APARTMENT }

will be converted to this:

interface AnalyticsPerson {
    fun live(): LiveLabel
}

interface LiveLabel {
    fun flat()
    fun house()
    fun apartment()
}

So the invocation of it will look like:
analyticsPerson.live().flat() instead of analyticsPerson.live(FLAT)

Moreover it can help to decrease number of duplication since there could be several action methods with same enum params, and when they will be used we can totally replace one invocation with another.

Add @Convention annotation for different naming conventions

Currently, the annotation will be used only for a class scope. And it will have a single parameter - an exact naming convention.

We will add few default conventions and we need to think to give a user possibility to introduce his own conventions.

In future, we need to add global settings for that.

Add global settings

We need to add global settings to setting up Ganalytics and possibly reduce number of annotations by customizing a default way of handle them

Add Postfixes

We need to think, if we have @HasPrefix/@NoPrefix annotations, does it necessary or at least fair to include @HasPostfix/@NoPostfix annotations?

Add @NoPrefix annotation is contrary to @Prefix

When #1 will be done, it will be needed to add a contrary annotation in case, if we will use @Prefix on an interface, but some methods must be used without prefixes.

P.S.: Of course, in that case, we can just split interface on two. First will use prefixes in all methods, and second will not. But the main idea behind several interfaces is to group actions by categories, where each interface represents its own category.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.