Tumgik
#consumerview
authortonichevelle · 6 years
Photo
Tumblr media
So I'm finally getting to part 2 of my #tankabar review (I had the spicy first and loved it). This is the original flavor I just tried, and once again they nailed it. Seasoning is on point, and the sweet, juicy cranberries pair so well with the tender, savory buffalo meat. A winner! 👍🏾👍🏾 #snacks #healthysnacks #productsatisfaction #productblogger #meatsnacks #productreview #instablogger #brandsatisfaction #consumersatisfaction #consumerview #tankabar #bloggerlife #author #motivationalspeaker #bosslady #brandbuilding (at Greenville, Mississippi)
0 notes
alifgiant · 4 years
Text
Perbedaan Sederhana dari MVC, MVP, MVVM dan MVI
Kita pasti sudah tidak asing dengan architecture design pattern yang saya sebutkan di judul (MVC, MVP, MVVM dan MVI). Semuanya mengajarkan mengenai bagaimana sebaiknya kita memisahkan code base kita agar mencapai konsep single responsibility (S) dari SOLID principle. Tentu saja penggunaan pattern tidak hanya terbatas disitu, tapi hal tersebut adalah yang paling jelas terlihat. Karena yang semulanya semua fungsionalitas berada dalam 1 objek, kini harus dipisahkan menjadi setidaknya 3 objek lain Model, View, dan Controller/Presenter/ViewModel/Intent.
Walaupun pattern ini sangat populer dan banyak sekali artikel yang membahasnya, tapi masih banyak yang kesulitan menjelaskan perbedaan antara ke-empatnya. Oleh karena itu saya akan mencoba menjelaskan hal tersebut melalui tulisan kali ini.
Model dan View
Kedua objek ini terdapat di semua pattern dan saya rasa sudah sangat jelas, sehingga tidak perlu saya ulangi penjelasannya... Tapi, demi kelengkapan artikel, mari saya coba jelaskan sekali lagi (alibi aja, emang mau ditulis 😜).
Model adalah objek yang merepresentasikan data yang akan ditampilkan oleh view. Sedangkan View adalah objek yang merepresentasikan apa saja interaksi yang dapat diterima/dilakukan oleh user dari/kepada sistem. View tidak melulu terkait tampilan yang dilihat di layar, untuk sistem yang lebih general, view bisa berupa daftar fungsi yang menerima input ataupun memberikan output.
Sebagai contoh, misal pada sistem pengaksesan data dari database. POJO (Plain Old Java Object) adalah Model, Database Driver (seperti Room, SqlHelper, ORM, dll) adalah Controller, dan kelas DatabaseHelper yang kalian buat untuk membungkus controller adalah View. Untuk lebih jelas silahkan lihat potongan code dibawah.
/** * Profile adalah Model * SqlHelper adalah Controller * DatabaseHelper adalah View */ class DatabaseHelper { val database = SqlHelper("mysql://192.168.0.10", "root", "root") fun openDatabase() { database.open() } fun closeDatabase() { database.close() } fun getUserProfile(id: String): Profile { val rawData = database.query(id) return parse(rawData) } }
Sekilas akan timbul pertanyaan kenapa perlu ada DatabaseHelper? Kan bisa langsung ke SqlHelper. Peryataan yang tepat, hal itu karena kita sedang menginspeksi scope database access saja. Code diatas memungkinkan kita mengganti ganti database tanpa perlu user dari DatabaseHelper mengetahuinya. Untuk scope yang lebih besar DatabaseHelper bisa dikategorikan sebagai controller, yang mana user sistem tersebut tidak perlu tau jika sewaktu waktu DatabaseHelper diganti menjadi ApiHelper.
Kalau kalian mencoba mengganti nama DatabaseHelper menjadi DatabaseView akan terdengar sangat rancu. Terlebih, karena objek DatabaseHelper hampir selalu digunakan oleh sistem yag lebih besar. Oleh karena itu pattern MVC sangat jarang, bahkan tidak pernah, digunakan untuk menggambarkan sistem selain yang memiliki tampilan.
Perbedaan Controller, Presenter, ViewModel, dan Intent.
Controller
Pada MVC, View merupakan "bos besar" dalam sistem ia pemilik dari 2 objek lainnya. Ibaratkan dalam sebuah kantor seorang bos mempekerjakan seorang OB. Bos tersebut menyuruh OB untuk membuatkan kopi. Lantas ia pergi ke toko membeli kopi bubuk, lalu kembali ke kantor, membuat kopi, lalu mengantarkannya kepada si bos. Si OB, "uang" dan kopi tersebut ya "milik" si bos (walaupun tentu saja OB bisa memiliki resource dia sendiri, misal sepeda motor). Dalam code digambarkan sebagai berikut.
/** * Money dan Coffee adalah Model * ShopController adalah Si OB "Controller" * ConsumerView adalah Si Bos "View" */ class CustomerView { var coffee = EmptyCoffeeCup() val shopper = ShopController() // si OB val person = PersonController() // otak si Bos fun onDrinkCoffeeClick() { val money = person.getMoney(15000) coffee = shopper.makeCoffee(money) person.consume(coffee) // coffee.volume -= 5 (minum dikit2) } }
Bisa dilihat dari code diatas sebuah view dapat memiliki banyak model dan banyak controller. Seperti layaknya seorang "bos". Permasalahan yang muncul adalah sistem yang tidak responsif. Hal ini karena MVC berfokus pada syncronous proses, menunggu adalah suatu hal yang wajar. Potongan code diatas akan membuat proses menunggu setiap eksekusi sampai selesai sebelum melanjutkan ke eksekusi berikutnya. Hal tersebut membuat tampilan seolah "freeze", atau tidak bergerak ketika sebuah eksekusi membutuhkan waktu yang lama. Hal ini dapat diakali dengan diperkenalkannya sistem callback dan thread. Potongan code tersebut dapat diubah menjadi seperti dibawah.
fun onDrinkCoffeeClick() { val money = person.getMoney(15000) shopper.makeCoffee( money, onCoffeeReady: (coffee) { person.consume(coffee) // coffee.volume -= 5 (minum dikit2) } ) }
Tapi bagaimana kalau ternyata getMoney juga lama? Karena person perlu ngambil uang dulu ke bank. Dan juga bagaimana kalau consume coffee juga lama? Karena dia menunggu dingin dulu? Selamat datang di Callback Hell 😈.
fun onDrinkCoffeeClick() { person.getMoney( 15000, onMoneyReady: (money) { shopper.makeCoffee( money, onCoffeeReady: (coffee) { person.consume( coffee, onCold: () { coffee.volume -= 5 } ) } ) } ) }
Presenter
Pada MVP, View dan Presenter memiliki kedudukan yang hampir setara. Mereka bisa saling menyuruh. Hanya saja, resource "model" ialah milik presenter yang mana ia yang memutuskan akan memberikan model apa kepada View. Relasi keduanya lebih kepada badan terhadap otak. Badan mengirim impuls ke otak, otak memprosesnya lalu mengirim balik impuls kepada otot badan. Contoh code diatas kini dapat diubah menjadi seperti berikut.
/** * Money dan Coffee adalah Model * CustomerPresenter adalah Otak "Presenter" * ConsumerView adalah Badan "View" */ class CustomerView { val presenter = CustomerPresenter() fun onStart() { presenter.start(this) } fun onDestroy() { presenter.stop() } fun onDrinkCoffeeClick() { presnter.drinkCoffee() } fun showDrinkAnimation() { ThreadUtils.scheduleMainThread { // open mouth, pick cup, etc.. } } } class CustomerPresenter() { lateinit var view: CustomerView? var coffee = EmptyCoffeeCup() val wallet = Wallet.get() val coffeeShop = ShopRepository() // coffee seller fun start(view: CustomerView) { this.view = view } fun stop() { this.view = null } fun makeCoffee() { val money = wallet.getMoney(15000) coffee = coffeeShop.buy(money) } fun drinkCoffee() { ThreadUtils.start { if (coffee is EmptyCoffeeCup) { makeCoffee() } coffee.volume -= 5 view?.showDrinkAnimation() } } }
Bisa dilihat diatas View dan Presenter saling memiliki reference terhadap satu sama lain. Sehingga bisa saling "menyuruh" yang mana walaupun sama-sama memanfaatkan threading tapi MVP menyelamatkan dari callback hell.
Namun masalah lain dapat timbul dari MVP yaitu MemoryLeak. MemoryLeak terjadi ketika view sudah berhenti digunakan namun presenter.stop() lupa dipanggil atau tidak terpanggil. Circular reference antara View dan Presenter akan membuat Garbage Collector (GC) tidak dapat meng-collect memori dari kedua object tersebut karena reference count nya masih belum 0. Hal ini dapat di hindari dengan menggunakan WeakReference (mengizinkan GC untuk melakukan pemutusan reference) terhadap view di presenter. Menjadi seperti berikut.
class CustomerPresenter() { lateinit var weakView: WeakReference ... fun start(view: CustomerView) { this.weakView = WeakReference(view) } ... fun drinkCoffee() { ... weakView.get()?.showDrinkAnimation() ... } }
ViewModel
Pada MVVM, VM berusaha menggabungkan kelebihan C dan P. VM tidak memiliki reference kepada View dan View tidak perlu menunggu proses pada VM tanpa terjebak ke callback hell. VM mempergunakan Observer Pattern kepada Model, dimana View melakukan observe (pengamatan terus menerus) kepada model sehingga jika terjadi perubahan maka ia akan tau. Relasi View kepada VM bisa diibaratkan seperti sutradara dan aktor. Sutradara bisa memerintah aktor melakukan sesuatu, tapi tidak sebaliknya. Sementara aktor menjalankan peran, sutradara terus menerus memperhatikan segala macam gerak dan membuat penyesuaian terhadap penempatan kamera. Mari kini kita coba refactor code sebelumnya.
/** * Money dan Coffee adalah Model * CustomerViewModel adalah Aktor "ViewModel" * CustomerView adalah Sutradara "View" */ class CustomerView { val vm = CustomerViewModel() fun onStart() { registerModel(vm) vm.scene.observeOnMainThread { currentScene -> if (currentScene == "drinking") { showDrinkAnimation() } } } fun onDrinkCoffeeClick() { vm.drinkCoffee() } fun showDrinkAnimation() { // open mouth, pick cup, etc.. } } class CustomerViewModel() { val scene = Observable() var coffee = EmptyCoffeeCup() val wallet = Wallet.get() val coffeeShop = ShopRepository() // coffee seller fun makeCoffee() { val money = wallet.getMoney(15000) coffee = coffeeShop.buy(money) } fun drinkCoffee() { ThreadUtils.start { if (coffee is EmptyCoffeeCup) { makeCoffee() } coffee.volume -= 5 scene.update("drinking") } } }
Bisa dilihat diatas tidak ada circular reference dan tidak ada callback hell. Akhirnya.. semuanya aman. Oh tidak secepat itu ferguso 🤭, "terus menurus" dalam code itu perlu di-define. Jika terus menerus itu artinya mengschedule tiap n detik atau n milidetik. Maka sistem akan tidak responsif (ketika perubahan terjadi maka update perlu menunggu schedule berikutnya) dan juga akan boros computing resource dari mesin. Karena akan banyak pengecekan yang tidak menemukan perubahan.
Oleh karena itu sebenarnya observable itu memegang reference kepada observernya. Dimana ketika value-nya berubah maka ia akan memberitahu kepada semua observernya, yang mana berarti potensi memory leak. Observable bisa menghindari Memory leak dengan menerapkan reference berupa WeakReference (lihat section sebelumnya) atau menerapkan mekanisme yang menjamin pemutusan reference ketika view akan di destroy, seperti yang dilakukan oleh LiveData di Android. Oleh karena itu MVVM dipopulerkan oleh kemunculan Android Architecture Component.
Intent
Last but not least, Intent pada MVI. Konsep MVI sangat mirip dengan MVVM dimana bergantung kepada adanya Model yang di observe. Bedanya ialah pada Intent sebuah action jika melakukan perubahan kepada sebuah model dianggap merubah keseluruhan model. Sehingga akan mentriger semua observer atau istilah lainnya akan melakukan full render. Hal tersebut tentu saja akan boros computing resource tapi hal ini seringkali preferable demi mencapai kondisi single source of truth. Sehingga menjamin tidak ada perubahan yang tidak terefleksi kepada tampilan. Misalnya contoh berikut.
var height = 172 var weight = 78 val bmiObservable = Observable(height/weight) bmiObservable.observe { bmi -> setText(bmi) } ... fun onUpdateHeightTextField(t: String) { height = t.toDouble() }
Ketika user memanggil fungsi onUpdateHeightTextField maka nilai bmiObservable tidak akan mentriger observer untuk melakukan setText. Sehingga solusi untuk permasalah diatas ialah membuat semua data menjadi observable seperti berikut.
val height = Observable(172) val weight = Observable(78) val bmiObservable = Observable(height/weight) height.observe { h -> bmiObservable.update(h/weight.value) } weight.observe { w -> bmiObservable.update(height.value/w) } ... bmiObservable.observe { bmi -> setText(bmi) } ... fun onUpdateHeightTextField(t: String) { height.update(t.toDouble()) }
Tapi solusi diatas membuat kita perlu mengganti semua data menjadi observable dan menambah banyak observer bantuan untuk sekedar mengupdate observer utama. Oleh karena itu dibuatlah solusi lebih elegan seperti berikut.
/** * State adalah Model */ class State ( val height: Double, val weight: Double ) class Intent { val state = Observable(State()) fun updateHeight(t: Double) { val newState = state.copyWith(height: t) state.update(newState) } } class View { val intent = Intent() fun onStart() { intent.state.observeOnMainThread { newState -> render(newState) } } fun render(state: State) { // do all view update base on state } fun onUpdateHeightTextField(t: String) { intent.updateHeight(t.toDouble()) } }
jika tidak menyukai immutable data, bisa juga menjadi..
class State ( var height: Double, var weight: Double ) class Intent { val state = Observable(State()) fun onUpdateHeightTextField(t: String) { state.value.height = t.toDouble() render() } fun render() { state.update(state.value) } }
solusi penulisan yang kedua membuat kita memiliki kontrol kapan ingin melakukan render. Sehingga bisa membatasi render hanya ketika diperlukan namun tetap reflect terhadap semua data.
Perlu diperhatikan juga, baik MVP, MVVM dan MVI juga tidak membatasi jumlah P, VM maupun I nya. Walaupun sering kali hanya ada 1.
Kesimpulan
Semua pattern memiliki kelebihan dan kekurangan masing-masing. Pemilihan pattern tergantung sesuai preferensi setiap coder, or at least preferensi kantor tempat coder bekerja 😂. Secara pribadi saya lebih menyukai MVI karena secara penulisan lebih sederhana dan menjamin tidak ada data yang tidak reflect walaupun dengan cost komputasi yang lebih besar. Namun kebetulan saya bekerja membuat aplikasi yang mana kemampuan komputasi walapun limited, semakin lama semakin bertambah cepat (Android dan iOS) sehingga beban komputasi yang tinggi tidak lagi signifikan. Walaupun dalam kondisi tertentu, saya bisa mengkombinasi penggunaan partialRender jika butuh melakukan optimasi.
Cukup sekian artikel kali ini. Semoga bermanfaat. Sampai ketemu di artikel berikutnya. Ciao~~
0 notes
hackernewsrobot · 6 years
Text
120M American Households Exposed In 'Massive' ConsumerView Database Leak
https://www.forbes.com/sites/thomasbrewster/2017/12/19/120m-american-households-exposed-in-massive-consumerview-database-leak/#412ed5e37961 Comments
0 notes
Text
Kenshoo teams up with Experian to offer third-party data for Facebook campaigns
The ad tech platform Kenshoo announced on Monday it has partnered with marketing data and services provider Experian.Kenshoo clients will be able to use Experian’s audience segments for Facebook ad targeting. The third-party data will initially be available for Facebook campaigns, with plans to expand to Amazon and Google.
Why you should care
After facing criticism for its handling of user data and new the regulatory provisions of GDPR, Facebook announced in March it was phasing out integrations with third-party data providers on its ad platform. Partnerships like the one between Kenshoo and Experian aim to give marketers back the ability to leverage third-party audience data in targeting their Facebook campaigns.
“While marketers know how valuable their first-party data can be and have certainly embraced second-party data targeting from ad giants like Google and Facebook, third-party data from trusted sources such as Experian can fill in the missing pieces in marketer data sets. For example, Experian can help target in-market auto buyers, niche demographic groups at scale, and past purchase behavior with rich audience data that would be very difficult for a single source to identify,” says Kenshoo chief product officer Zvika Goldstein.
More on Kenshoo’s announcement and third-party data
The partnership will apply to all of Experian’s ConsumerView data sets — a list that includes 1,159 audience segments.
The deal comes as the use of third-party data has faced increasing scrutiny, in large part due to regulatory and privacy advocacy pressures.
Kenshoo laid out a defense of third-party data in its announcement. It cited several studies such as one from Duke University’s Fuqua School of Business, the American Marketing Association (AMA) and Deloitte in August that found 91 percent of marketers have increased or kept their third-party data usage the same over the last two years.
This story first appeared on MarTech Today. For more on marketing technology, click here.
The post Kenshoo teams up with Experian to offer third-party data for Facebook campaigns appeared first on Marketing Land.
from Marketing Land https://ift.tt/2FxVKpm
0 notes
foreverisnowforever · 6 years
Photo
Tumblr media
120 Million American Households Exposed In 'Massive' ConsumerView Database Leak
0 notes
chrisshort · 6 years
Link
0 notes
superfreakinlonely · 6 years
Link
120M American Households Exposed In 'Massive' ConsumerView Database Leak 444 by wglb
0 notes
casualmoonbird-blog · 6 years
Text
120M American Households Exposed In 'Massive' ConsumerView Database Leak
0 notes
Link
120M American Households Exposed In 'Massive' ConsumerView Database Leak http://ift.tt/2CDWfYT got 444 points on Hacker News
0 notes
authortonichevelle · 6 years
Photo
Tumblr media
Y'all! See, it's snacks like this that give me life! Poppables by @lays are the truth! So crisp, super light and airy, with just the right amount of sea salt. No guilt or shame in my #snack game! These are so good, two thumbs up! 👍🏾👍🏾 #lays #poppables #snacktime #productsatisfaction #productblogger #productreview #instablogger #brandsatisfaction #consumerview #consumersatisfaction #bloggerlife #momlife #brandbuilding #influencer #plannergirl #goodeats #funtimes (at Greenville, Mississippi)
0 notes
baileyspecialrisks · 6 years
Link
As long as they knew the right URL to visit, an Amazon Web Services user could retrieve all the data, which was left online by marketing analytics company Alteryx.
0 notes
allfunoff · 6 years
Link
120M American Households Exposed In 'Massive' ConsumerView Database Leak 332 by wglb |
0 notes
mrfamous001 · 6 years
Link
120M American Households Exposed In 'Massive' ConsumerView Database Leak 335 by wglb | 117 comments on Hacker News.
0 notes
foreverisnowforever · 6 years
Photo
Tumblr media
120 Million American Households Exposed In 'Massive' ConsumerView Database Leak
0 notes
its-satiya-me · 6 years
Text
New top story on Hacker News: 120M American Households Exposed In 'Massive' ConsumerView Database Leak
120M American Households Exposed In 'Massive' ConsumerView Database Leak 330 by wglb | 117 comments on Hacker News. from Blogger http://ift.tt/2DdIi4L
0 notes
kenweene · 6 years
Text
120 million American households exposed in 'massive' ConsumerView database leak
See on Scoop.it - Upsetment
A huge database containing vast amounts of revealing data on Americans' everyday lives has been left exposed on Amazon Web Services.
Kenneth Weene's insight:
The other day, I looked at some socks on line. Now, everywhere I go on the internet I see ads for that sock company. If I wanted them, I would have bought them. But, does that stop the marketing machinery? Of course not. We have become nothing but data to the world of number crunching corporations and marketing firms. No wonder none of us want to answer the phone when we get so many robocalls. No wonder none of us want to give honest answers when we are bombarded with push surveys. Just one more reason for us to be angry. Now these jugheads say it doesn't matter that they have put all kinds of personal information out there since our names weren't attached, like it would be that difficult to figure out which house or apartment went with which data. Sometimes I think those folks living under the overpass down the road have a better idea. If you don't have an identity, you don't have to worry about it being stolen. If you don't have possessions, you don't have to worry about safeguarding them. 
Am I the only one who wishes we could take a few steps back. Of course, when I was a kid, the operators at the Buckfield exchange knew all our business. On the other hand, there wasn't anybody who wanted to buy that information from them. Oh, for a world of somewhat privacy. 
Speaking of Buckfield, have you read Broody New Englander, my paean to the Maine of my youth? It really is one of those books that people should read:
https://www.amazon.com/Broody-New-Englander-Kenneth-Weene/dp/1502759284/ref=asap_bc?ie=UTF8
0 notes