架构探险-轻量级微服务架构

This series takes a basic MVP app using Retrofit and RxJava to display a list of Github repositories; and converts it into a modern Android app — along the way it will give an introduction to a variety of techniques used when architecting Android apps, explain why those techniques are used, and perform a few experiments to boot.

本系列使用一个基本的MVP应用程序,该应用程序使用Retrofit和RxJava来显示Github存储库列表。 并将其转换为现代的Android应用程序-在此过程中,它将介绍架构Android应用程序时使用的各种技术,解释为什么使用这些技术,并执行一些启动实验。

If you just want to see the code go here the repo will be updated as the series progresses.

如果您只想查看代码,请在此系列进行过程中更新仓库。

Part 1 — Simple dependency injection with Dagger

第1部分-使用Dagger进行简单的依赖注入

Part 2 — Converting Presenters into ViewModels

第2部分-将演示者转换为ViewModels

Part 3— Single activity architecture + some funky Dagger

第3部分-单活动架构+一些时髦的Dagger

To follow along, this is the project after using MVVM. The next change will be to make use of single activity architecture and the navigation androidx library, plus there’s something funky we can do with Dagger. If you’re comfortable converting activities to fragments, skip on to halfway through the post.

接下来 , 这是使用MVVM之后的项目 。 下一个更改将是利用单一活动架构和导航androidx库,此外,我们可以使用Dagger做一些时髦的事情。 如果您愿意将活动转换为片段,请跳到帖子的一半。

2020年的碎片 (Fragments in 2020)

Fragments have come a long way since an infamous Advocating Against Fragments post by square in 2014. Back then Fragments were complex to navigate between, bug prone, and had a cumbersome lifecycle.

自从2014年臭名昭著的提倡“碎片倡导”以来,碎片就已经走了很长一段路。那时,碎片在导航之间很复杂,容易出错,并且生命周期繁琐。

Fast forward to 2020 and the androidx navigation library solves fragment navigation, bugs are few and far between, and the lifecycle…well the lifecycle is still quite cumbersome.

快进到2020年,androidx导航库解决了片段导航,错误很少且相差甚远,而且生命周期…嗯,生命周期仍然很麻烦。

But, for better or worse, single activity architecture is the recommended approach from Google and seems to be the future of Android development. So lets go ahead and convert this project to single activity architecture, and see some of the benefits it can bring.

但是,无论好坏,单一活动架构是Google推荐的方法,并且似乎是Android开发的未来。 因此,让我们继续将该项目转换为单一活动架构,并了解它可以带来的一些好处。

一项活动 (A single activity)

This will be the only activity in the entire app, conceptually similar to your application class, but specific to your apps UI. All our fragments will be launched within this activity.

这将是整个应用程序中的唯一活动,从概念上讲类似于您的应用程序类,但特定于您的应用程序UI。 我们的所有片段都将在此活动中启动。

As it’s our only activity a good place to put it can be as a direct descendent of the UI folder.

因为这是我们的唯一活动,所以可以将它放置为UI文件夹的直接后代。

将活动变形为碎片 (Morphing Activities into Fragments)

Currently there are two screens, both activities. Both these activities extend BaseActivity. So the change here is simple, rename the base activity and change the class it extends.

当前有两个屏幕,均处于活动状态。 这两个活动都扩展了BaseActivity。 因此,此处的更改很简单,重命名基础活动并更改其扩展的类。

Inheritance can sometimes receive its fair share of flak, but used well, it can make code changes a breeze. In this case our BaseActivity contains all our common screen based logic which applies equally well to fragments. Here we only have 2 activities to refactor, but imagine a larger app with 10 or 20? By changing one line every Fragment has all the common screen behaviour we need.

继承有时可以得到应有的帮助,但使用得当,可以使代码更改变得轻而易举。 在这种情况下,我们的BaseActivity包含我们所有基于屏幕的通用逻辑,这些逻辑同样适用于片段。 在这里,我们只有2个活动可重构,但想象一个更大的应用程序(包含10或20)? 通过更改每一行,每个Fragment都具有我们所需的所有常见屏幕行为。

There are areas of programming that are regularly abused — inheritance being one of those — but often these areas are also very powerful. Instead of avoiding those areas, a better strategy can be to learn when they’re useful and when they’re not so useful.

有些编程领域经常被滥用-继承就是其中之一-但通常这些领域也非常强大。 除了避开这些领域,更好的策略可以是学习它们何时有用,何时不那么有用。

But there’s still some work to do to make our screens work with the fragment lifecycle.

但是,仍有一些工作要做,以使我们的屏幕在片段生命周期中正常工作。

片段生命周期 (Fragment lifecycle)

In an Activity most view initialisation code goes in onCreate. A fragment has a significantly more complex lifecycle. There’s a lot of choice when it comes to choosing where to put the code which initialises your view. I try to use:

Activity大多数视图初始化代码都放在onCreate 。 片段的生命周期要复杂得多。 在选择将代码初始化视图的位置时,有很多选择。 我尝试使用:

  • onCreate for initialising data, e.g. fetching values from the Bundle.

    onCreate用于初始化数据,例如从Bundle中获取值。

  • onCreateView for inflating views. In recent versions of the androidx fragment library the layout id can be passed directly into the constructor, as I plan to add data binding to this project, I won’t use that functionality here.

    onCreateView用于扩大视图。 在最新版本的androidx片段库中,布局ID可以直接传递到构造函数中,因为我计划将数据绑定添加到该项目中,因此在此我将不使用该功能。

  • onViewCreated for putting views in the their correct state, e.g. applying listeners and initial values.

    onViewCreated用于将视图置于正确的状态,例如,应用侦听器和初始值。

  • onStart/onStop etc. as usual

    照常onStart / onStop

There’s a lot of conflicting advice on which lifecycle methods are best to use for what. Ultimately, find a structure you like and stick to it throughout your project. And if you’re ever unsure on which lifecycle method to use, check the fragment source code — it’s well documented and can tell you exactly when various lifecycle methods are called to suit your purposes.

关于哪种生命周期方法最适合用于什么有很多相互矛盾的建议。 最终,找到您喜欢的结构并在整个项目中坚持下去。 并且,如果您不确定要使用哪种生命周期方法,请检查片段源代码-它有充分的文档记录,可以准确地告诉您何时调用各种生命周期方法以适合您的目的。

And the Main Fragment

和主要片段

Although this step is quite time consuming, there’s nothing complex here. All the code stays exactly the same, it’s just rearranged into new lifecycle methods.

尽管此步骤非常耗时,但这里没有什么复杂的。 所有代码都完全相同,只是重新排列成新的生命周期方法。

需要活动的代码 (Code that needs an Activity)

There are always some places in a fragment where you’ll need access to the activity or context. But there’s no guarantee in the api that the context or activity will be non-null when you need it. So to avoid a mountain of null checks, the androidx libraries helps you out.

片段中总是存在一些需要访问活动或上下文的地方。 但是在api中不能保证上下文或活动在需要时不会为空。 因此,为了避免大量的null检查,androidx库可以帮助您。

Toast.makeText(requireContext(), it.error, Toast.LENGTH_LONG).show()

There’s also a requireActivity method if needed. And for cases where you specifically need an AppCompatActivity, ComponentActivity, or even your single activity (AndroidPlaygroundActivity)— you can create your own extension function.

如果需要,还有一个requireActivity方法。 对于特别需要AppCompatActivityComponentActivity甚至是单个活动( AndroidPlaygroundActivity )的情况,您可以创建自己的扩展功能。

fun Fragment.requireAppCompatActivity(): AppCompatActivity {return requireActivity() as? AppCompatActivity?: throw IllegalStateException("Activity this fragment is attached to does not extend AppCompatActivity")
}
requireAppCompatActivity().supportActionBar?.title = it.toolbarTitle

When using these methods just be aware that it isn’t completely clean. By using methods such as these we are making assumptions about where the fragment is being used and what state the fragments in. Most of the time thats fine, but sometimes it’s not.

使用这些方法时,请注意它并不完全干净。 通过使用诸如此类的方法,我们对片段的使用位置和片段的状态进行了假设。在大多数情况下,这很好,但有时并非如此。

更新清单 (Update the manifest)

With all our screens converted to Fragments, our Manifest can now be significantly simplified — with a single Activity declaration!

将所有屏幕转换为片段后,现在可以通过单个Activity声明来显着简化清单。

<activity android:name=".ui.AndroidPlaygroundActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity>

And that’s it, single activity architecture is ready (minus navigation). You can manually navigate between fragments, but that’s often complex and bug prone. With the navigation androidx library, navigation is a breeze. There’s a lot of great docs and articles out there on the navigation library so I won’t go into how to set it up here. But you can look at the repository to see it in action.

就是这样,单活动架构已准备就绪(减去导航)。 您可以手动在片段之间导航,但这通常很复杂且容易出错。 使用导航androidx库,导航变得轻而易举。 导航库中有很多很棒的文档和文章,所以我不会在这里进行设置。 但是您可以查看存储库以了解其运行情况。

时髦的依赖注入 (Funky dependency injection)

Now the interesting bit!

现在有趣的一点!

更新17/06/2020: (Update 17/06/2020:)

With the alpha release of hilt dependency injection with Dagger is about to get a hell of a lot easier! Hilt is an opinionated library over the top of dagger that removes almost all boilerplate dagger code. It makes DI simpler and attempts to standardise how DI is written in Android. From an early look it’s a huge improvement and is sure to become the favoured approach for DI in Android.

随着Dagger 的hilt依赖注入的alpha版本的发布,地狱将变得容易得多! Hilt是匕首上方的自定义库,可删除几乎所有样板匕首代码。 它使DI变得更简单,并试图标准化DI在Android中的编写方式。 从早期的角度来看,它是一个巨大的改进,并且肯定会成为Android中DI的首选方法。

The rest of this article goes into some principles about DI, but be aware that with the release of hilt the DI method used in this article should be considered legacy and is actually much easier to achieve with hilt.

本文的其余部分介绍了有关DI的一些原则,但是请注意,随着hilt的发布,本文中使用的DI方法应被认为是旧有的,实际上,使用hilt可以轻松实现。

新组件 (A new component)

So far our Dagger setup has been made of a single component — AndroidPlaygroundComponent — and every object within that component has access to every other object. That works fine for simple apps, but as apps get bigger we often need to create additional components which only have access to a limited selection of objects.

到目前为止,我们的Dagger设置由单个组件AndroidPlaygroundComponent组成,该组件中的每个对象都可以访问其他每个对象。 对于简单的应用程序来说,这很好用,但是随着应用程序变得越来越大,我们经常需要创建只能访问有限对象选择的其他组件。

To try this out lets create a second component…in fact we’ve already been creating additional components, every time @ContributesAndroidInjector is used, Dagger is creating a (Android specific) subcomponent behind the scenes for reasons I won’t go into here — suffice to say the Android OS is not DI friendly.

要尝试进行此操作,请创建第二个组件……事实上,我们已经在创建其他组件,每次使用@ContributesAndroidInjector ,Dagger都会在幕后创建一个(特定于Android的)子组件,原因是我不会在这里介绍–足以说Android操作系统不兼容DI。

With knowledge of @ContributesAndroidInjector, it’s easy to create a component for our single activity which contains scoped objects that can only be accessed by other objects in the same component (psst. this means all these objects can only be alive while the Activity is alive).

有了@ContributesAndroidInjector知识,很容易为我们的单个活动创建一个组件,该组件包含只能由同一组件中的其他对象访问的作用域对象(psst。这意味着所有这些对象只能在Activity处于活动状态时处于Activity状态) 。

@Module
interface SingleActivityModule {@SingleActivity@ContributesAndroidInjector(modules = [MyScopedModule::class])fun androidPlaygroundActivity(): AndroidPlaygroundActivity
}@Module
interface MyScopedModule {@Bindsfun objectOne(objectOneImpl: ObjectOneImpl): ObjectOne@Bindsfun objectTwo(objectTwoImpl: ObjectTwoImpl): ObjectTwo
}

The @ContributesAndroidInjector annotation takes a modules parameter which defines all the objects available to this component. Every object within @ContributesAndroidInjector can access every other object. But if you try to inject the object into another component, dagger will throw a compile time error.

@ContributesAndroidInjector批注采用modules参数,该参数定义了此组件可用的所有对象。 @ContributesAndroidInjector每个对象都可以访问其他每个对象。 但是,如果您尝试将对象注入到另一个组件中,则匕首将引发编译时错误。

What about if we need an object fromAndroidPlaygroundComponent ? No problem, each subcomponent has access to all the objects in it’s parent component, grandparent component, great-grandparent component, and so on.

如果我们需要AndroidPlaygroundComponent的对象怎么办? 没问题,每个子组件都可以访问其父组件,祖父母组件,曾祖父母组件等中的所有对象。

向图中添加片段 (Adding Fragments to the graph)

As we’re using single activity architecture, fragments can only ever exist in the single activity. So they should also be scoped to the Activity component.

当我们使用单一活动架构时,片段只能存在于单一活动中。 因此,它们也应仅限于“ Activity组件。

@Module
interface SingleActivityModule {@SingleActivity@ContributesAndroidInjector(modules = [MyScopedModule::class,FragmentModule::class])fun androidPlaygroundActivity(): AndroidPlaygroundActivity
}
@Module
interface FragmentModule {@ContributesAndroidInjectorfun mainFragment(): MainFragment@ContributesAndroidInjectorfun detailsFragment(): DetailsFragment
}

You’ll notice that the fragments use @ContributesAndroidInjector, this is again due to Androids DI unfriendliness which means Dagger needs to create a new subcomponent for each Fragment.

您会注意到片段使用@ContributesAndroidInjector ,这又是由于Android的DI不友好,这意味着Dagger需要为每个Fragment创建一个新的子组件。

You might rightly say here that Fragments shouldn’t know about each other in the DI graph. No problem, subcomponents can’t use objects in other subcomponents that are not their parent. So in our dagger world, MainFragment has no knowledge of DetailsFragment and visa versa.

您在这里可能会正确地说,碎片在DI图中不应该彼此了解。 没问题,子组件不能使用不是其父级的其他子组件中的对象。 因此,在我们的匕首世界中, MainFragment不了解DetailsFragment ,反之亦然。

但是为什么这有用呢? (But why is this useful?)

Take something like navigation, in most Android apps the code for navigation is scattered throughout our screens. This breaks many fundamental principles of good architecture. Which you realise when upgrading to the androidx navigation library — a change needs made to EVERY screen, in large apps this becomes extremely cumbersome. Simply put, scattered responsibility is hard to maintain and bug prone.

例如导航,在大多数Android应用中,导航代码分散在我们的屏幕上。 这打破了良好架构的许多基本原则。 升级到androidx导航库时,您意识到了这一点-需要对每个屏幕进行更改,在大型应用程序中,这变得非常麻烦。 简而言之,分散的责任很难维护并且容易出错。

Architectural principles often encourage abstracting responsibility behind interfaces so that responsibility becomes an implementation details — easy to swap in and out without effecting the rest of the app. These days this is commonly encouraged for the data layer of the app and implementation details like Retrofit are often hidden behind interfaces. So why not use the same concept in the view layer of our app?

架构原则通常鼓励在接口后抽象责任,以使责任成为实现的细节—易于调换,而不会影响应用程序的其余部分。 如今,通常在应用程序的数据层鼓励这样做,而诸如Retrofit之类的实现细节通常隐藏在界面后面。 那么,为什么不在我们的应用程序的视图层中使用相同的概念呢?

抽象导航 (Abstracting navigation)

What if our Fragment has no knowledge of how navigation occurs? Instead fragments use a simple navigation interface to order navigation. This simplifies fragments by limiting their responsibility and encourages composable behaviour in the UI — reducing code duplication.

如果我们的Fragment不知道导航如何发生怎么办? 相反,片段使用简单的导航界面来排序导航。 这通过限制片段的责任来简化片段,并在UI中鼓励可组合的行为-减少代码重复。

interface Navigator {fun goToDetailsFromMain(githubRepoEntity: GithubRepoEntity)fun goToUrl(url: String)
}

As this is code which has no connection to Android, this could now live in your business layer (but preferably your view model layer if your app has that many layers). And the implementation would live on your Android layer.

由于这是与Android无关的代码,因此它现在可以存在于您的业务层中(但如果您的应用程序具有那么多的层,则最好是您的视图模型层)。 实现将在您的Android层上进行。

@SingleActivity
class NavigatorImpl @Inject constructor(private val androidPlaygroundActivity: AndroidPlaygroundActivity
): Navigator {override fun goToDetailsFromMain(githubRepo: GithubRepoEntity) {val action = MainFragmentDirections.actionMainFragmentToDetailsFragment(githubRepo)androidPlaygroundActivity.findNavController(R.id.nav_host_fragment).navigate(action)}override fun goToUrl(url: String) {Intent(Intent.ACTION_VIEW, Uri.parse(url)).startActivity(androidPlaygroundActivity)}
}

Usually the only requirement of navigation code is that it has an Activity reference. Luckily we added our single activity to the dagger graph earlier so it can be injected into our implementation. And as the Navigator is scoped to the Activity it can only be used inside the subcomponents object graph — so only while the Activity is alive.

通常,导航代码的唯一要求是它具有Activity引用。 幸运的是,我们将我们的单个活动添加到了匕首图中,因此可以将其插入到我们的实现中。 而且,由于Navigator的作用域是Activity ,因此只能在子组件对象图中使用它-仅当Activity处于Activity时才可以使用。

在哪里调用导航器 (Where to call the Navigator)

This is a little more tricky.

这有点棘手。

The simple answer is to inject the Navigator into your fragment and call it from there.

简单的答案是将Navigator注入片段并从那里调用它。

But there is another possibility. Anyone that’s used MVVM in Android will be familiar with one-time actions — there’s a host of medium articles on the subject. For example, the view model wants to display a toast but only wants to display it once, so has to reset view state after the toast is displayed to avoid re-showing the toast after an event such as a screen rotation.

但是还有另一种可能性。 任何在Android中使用过MVVM的人都会熟悉一次性操作-有关该主题的文章很多。 例如,视图模型只想显示一个Toast,但只想显示一次,因此必须在显示Toast之后重置视图状态,以避免在屏幕旋转等事件后重新显示Toast。

As the navigator now uses a similar concept to business logic, and our view models will only exist while an activity exists, our view models can become part of the activity subcomponent, and the navigator can be injected directly into the view model constructor.

由于导航器现在使用与业务逻辑类似的概念,并且我们的视图模型仅在活动存在时存在,因此我们的视图模型可以成为活动子组件的一部分,并且可以将导航器直接注入到视图模型构造函数中。

This means there’s no need to expose one time actions such as navigation through view states. And your view models becomes as simple as:

这意味着无需公开诸如浏览视图状态之类的一次性动作。 您的视图模型变得简单:

fun repoClicked(githubRepoEntity: GithubRepoEntity) {navigator.goToDetails(githubRepoEntity)
}
fun onGoToRepositoryClicked() {navigator.goToUrl(githubRepoEntity.url)
}

This is now super simple to test or debug, your navigation code is abstracted to a single class, plus no fancy one-time actions are needed in your view states.

现在,这非常易于测试或调试,您的导航代码被抽象为一个类,并且在视图状态中不需要花哨的一次性操作。

The only downfall of this approach is that if you’re using the androidx ViewModel this approach WON’T WORK. The reason being that the ViewModel has a longer lifecycle than an Activity. By using this method you’d be indirectly adding a reference to the Activity within the ViewModel. Therefore on every screen rotation, Activity would leak. There are ways you could get round that, but nothing pretty.

这种方法的唯一缺点是,如果您使用的是androidx ViewModel此方法将无效。 原因是ViewModel的生命周期比Activity更长。 通过使用此方法,您将在ViewModel间接添加对Activity的引用。 因此,在每次屏幕旋转时, Activity都会泄漏。 有很多方法可以解决这个问题,但是没有什么好看的。

So if you’re using ViewModel you’re stuck injecting the navigator into the Fragment.

因此,如果您使用ViewModel ,则必须将导航器注入Fragment

扩展概念 (Extending the concept)

You can even extend the same concept to Toasts, Snackbars, Keyboard listening, and much more. In the final code for this section I’ve solved the bug mentioned at the end of the last article by using this same structure for Toasts. Essentially a whole variety of code in the view layer of an app can follow strong architectural principles and be styled as focused classes of responsibility — all by using the power of dependency injection.

您甚至可以将相同的概念扩展到Toasts,小吃店,键盘监听等等。 在本节的最终代码中 ,我通过使用与Toasts相同的结构解决了上一篇文章结尾提到的错误。 本质上,应用程序视图层中的所有各种代码都可以遵循强大的体系结构原理,并可以将其样式化为重点责任类别-所有这些都可以利用依赖注入的能力来实现。

结论 (Conclusion)

Single activity architecture is a step up in Android development, and with the navigation library, converting a codebase to this structure can be a breeze. It also opens up some interesting architecture patterns which now require less boilerplate.

单一活动架构是Android开发中的一大步,借助导航库,将代码库转换为这种结构很容易。 它还打开了一些有趣的架构模式,这些模式现在需要更少的样板。

The ideas in the second half of the article attempt to solve a common problem with Android view code where — even in well architected codebases — many fundamental principles such as SOLID are forgotten and features like navigation are scattered throughout Activities and Fragments.

本文下半部分的想法试图解决Android视图代码的一个常见问题,即使在结构良好的代码库中,也忘记了许多基本原理,例如SOLID ,而导航等功能则分散在整个Activity和Fragments中。

The overriding principle is that just like any other layer of your app, the view layer can be architected as focused classes of composable behaviour. This makes it easy to modify UI down the line, changing from Snackbars to Dialogs to show announcements? A single class can be changed to modify how announcements throughout the app are displayed. Updating to the androidx navigation library? Again, a single class needs modified.

首要原则是,就像应用程序的其他任何层一样,视图层也可以设计为可组合行为的重点类。 这样可以很容易地修改UI,从Snackbars更改为Dialogs以显示公告? 可以更改一个班级,以修改整个应用程序中公告的显示方式。 更新到androidx导航库? 同样,单个类需要修改。

Many parts of your view become implementation details — simple to swap in and out without effecting the rest of your app.

视图的许多部分都变成了实现细节-可以在不影响应用程序其余部分的情况下轻松切入和切出。

On top of this, testing becomes simpler. For standard unit tests too much much responsibility leads to long, hard to write and maintain tests — a code smell. The same holds true for UI tests, by making our view layer composable, UI tests are far easier to write and maintain.

最重要的是,测试变得更加简单。 对于标准的单元测试,太多的责任导致了漫长,难以编写和维护的测试-代码的味道。 UI测试也是如此,通过使我们的视图层可组合,UI测试的编写和维护要容易得多。

I’ve used this approach in a few apps, and I’ve found that it makes developing easier, less code is duplicated, bugs are less common, and most importantly, large UI changes become a breeze. So what do you think? Is this approach useful?

我已经在一些应用程序中使用了这种方法,并且发现它使开发变得更容易,重复代码更少,错误很少见,并且最重要的是,大的UI更改变得轻而易举。 所以你怎么看? 这种方法有用吗?

Final code for this section is here.

本节的最终代码在这里 。

翻译自: https://proandroiddev.com/part-3-single-activity-architecture-514791724172

架构探险-轻量级微服务架构


http://www.taodudu.cc/news/show-4338621.html

相关文章:

  • 2013年Devoxx法国-第3天
  • 金九银十,为期2周的前端面经汇总(初级前端)
  • 使用Echars实现水滴状、环形图、分割图、堆叠、组织架构图、地图轮廓等图表
  • pyecharts绘制日历图、漏斗图、仪表盘、水滴图
  • 使用css实现水珠/水滴效果
  • 用echarts实现水滴图效果
  • 用python模拟微信支付实现付款功能_mpvue1.0+python3.7+Django2.0.4实现微信小程序的支付功能...
  • 用python模拟微信支付实现付款功能_Python实现微信小程序支付功能
  • php实现自动续费功能,如何关闭wps自动续费
  • android自动微信支付平台,android接入微信支付SDK
  • php扣费代码,微信支付-扣费服务开发者文档
  • 高等数学(第七版)同济大学 习题3-7 个人解答
  • 高等数学(第七版)同济大学 习题6-2 (后18题)个人解答
  • 《高等数学》 第七版 同济大学
  • RFS[4]: No standby redo logfiles available for thread 1
  • RFS_关键字
  • RFS 理解
  • oracle外部表kup-04023,Oracle Data Guard 主库报--RFS Possible network disconnect with primary database...
  • linux RFS
  • 【DB笔试面试755】在Oracle的DG中,RFS、LNSn、MRP、LSP进程的作用分别是什么?
  • OKR工作法——宏观总结
  • 如何利用番茄工作法提高学习和工作的效率
  • 一篇文章读懂《麦肯锡极简工作法》
  • pytorch操作基礎(二)——基礎
  • Jsp之神笔记
  • minecraft1.16java_我的世界:1.16最神奇的种子,自然生成的石头雕像,基岩能用!...
  • [笔记]n个点的基环树数量
  • 奥丁神叛虚拟机 台服登录不上游戏 账号无法登录游戏解决办法
  • 构建完整的API构架与Buddy API使用示例
  • android.view.ContextThemeWrapper cannot be cast to android.app.Activity

架构探险-轻量级微服务架构_第3部分-单活动架构+一些时髦的Dagger相关推荐

  1. 跟着《架构探险》学轻量级微服务架构 (一)

    架构探险 微服务概念这两年已经火遍大江南了,但在实际的开发和使用中,用到的还是挺少的,尤其对创业团队来说. 在上一个产品中,我们也在把传统的开发模式,不断往「微服务」方向靠拢.但终究还是处于学习阶段. ...

  2. C++轻量级微服务_从微服务架构解析信源新一代“金融e采”产品

    金融电采,信源信息 信源信息从事电子化采购软件开发已经有15个年头,进行金融保险类采购系统的开发也已经有十多年了. 信源信息针对金融领域客户量身定做的"金融e采"产品线,以前瞻的技 ...

  3. go 微服务框架_清晰架构(Clean Architecture)的Go微服务

    更新 我最进对这个框架进行了重大升级,虽然所做的改动不大,但成效显著.这次更新修复了旧框架中的所有主要问题,尽管它的的主要项目结构和接口都没有改变,具体改动内容请参见清晰架构(Clean Archit ...

  4. c# 微服务学习_资深架构师学习笔记:什么是微服务?

    们先来看看为什么要考虑使用微服务. 构建单体应用 我们假设,您开始开发一个打车应用,打算与 Uber 和 Hailo 竞争.经过初步交流和需求收集,您开始手动或者使用类似 Rails.Spring B ...

  5. dubbo协议_阿里P8架构师谈微服务架构:Dubbo+Docker+SpringBoot+Cloud

    微服务架构 什么是微服务架构呢?简单说就是将一个完整的应用(单体应用) 按照一定的拆分规则(后文讲述)拆分成多个不同的服务,每个服务都能独立地进行开发.部署.扩展.服务于服务之间通过注入RESTful ...

  6. 单体 soa 微服务 区别_漫谈何时从单体架构迁移到微服务?

    面对微服务如火如荼的发展,很多人都在了解,学习希望能在自己的项目中帮得上忙,当你对微服务的庐山真面目有所了解后,接下来就是说服自己了,到底如何评估微服务,什么时候使用微服务,什么时间点最合适,需要哪些 ...

  7. 微服务架构图_漫谈何时从单体架构迁移到微服务?

    面对微服务如火如荼的发展,很多人都在了解,学习希望能在自己的项目中帮得上忙,当你对微服务的庐山真面目有所了解后,接下来就是说服自己了,到底如何评估微服务,什么时候使用微服务,什么时间点最合适,需要哪些 ...

  8. 微服务实战(七):从单体式架构迁移到微服务架构

    http://dockone.io/article/1266 希望读者通过本系列文章对微服务优缺点有一个比较好的理解,以及何时使用这种架构.也许微服务架构比较适合你的应用.也许你正在开发一个大型.复杂 ...

  9. 微服务实践(七):从单体式架构迁移到微服务架构

    迁移到微服务综述 迁移单体式应用到微服务架构意味着一系列现代化过程,有点像这几代开发者一直在做的事情,实时上,当迁移时,我们可以重用一些想法. 一个策略是:不要大规模(big bang)重写代码(只有 ...

最新文章

  1. usaco Healthy Holsteins
  2. Spring MVC+Spring+Mybatis实现支付宝支付功能(图文详解+完整代码)
  3. 为什么await()后会执行lock.unlock,await()时不就释放锁了吗
  4. 设计模式:结构型模式
  5. 20090701随笔
  6. 执行python时,ImportError: No module named xxx的解决方法
  7. Groovy里读写本地文件的几种方式
  8. ios 系统提示框_ios13终于能屏蔽系统更新了!附详细教程
  9. Windows系统下,Android Studio的安装
  10. linux ftp mysql_linux下ftp和ftps以及ftp基于mysql虚拟用户认证服务器的搭建
  11. mysql时间戳转日期
  12. python2没有pip命令_解决Windows下python和pip命令无法使用的问题
  13. MySQL distinct多个字段
  14. Linux学习笔记十七——Linux系统启动流程
  15. Magento开发文档(二):Magento配置
  16. 【SQL精彩语句】按某一字段分组取最大(小)值所在行的数据
  17. fbinstool linux iso,大神给你传授fbinsttool下载 【操作教程】 的详细_
  18. 联想·云计算中心运维服务(1+X中级)教材出版
  19. 为什么要有域名,看完你就懂了。
  20. 驱动篇 -- 继电器

热门文章

  1. https域名安全证书怎么配置
  2. NDIS小端口驱动ndisEdge学习二——小端口驱动的初始化
  3. java web atm机_Java项目实现模拟ATM机
  4. 印象笔记Mac版的快捷键有哪些?
  5. Android系统换字体不root,小编吐血整理,超实用免ROOT 安卓手机换字体软件
  6. jsp登录页面密码equals验证出现问题解决办法
  7. LoRaWAN协议入网方式
  8. zigbee判断首次入网
  9. 计算机管理打印机服务,win7系统打印机服务怎样开启 开启打印机服务的设置方法...
  10. Python批量统计数据分布的偏度并画图