How do you refactor entrypoint classes in an Application? - oop

I have this existing class setup. This is my entrypoint class.
public class AppManager {
public AppManager() {
}
public void startApp(){
doInit();
if(doTask1())
doTask2();
else
doTask3();
createUI()
}
public void doInit() {
InitClass initClass = new InitClass();
initClass.init();
}
public boolean doTask1() {
Task1 task1 = new Task1();
return task1.doTask();
}
public boolean doTask2() {
Task2 task2 = new Task2();
return task2.doTask();
}
public boolean doTask3() {
Task3 task3 = new Task3();
return task3.doTask();
}
public void createUI() {
UIManager uiManager = new UIManager();
uiManager.createUI();
}
public static void main(String[] args) {
AppManager appManager = new AppManager();
appManager.startApp();
}
}
I wanted to do some refactoring of it. I think it is doing a bit of things but I don't know how?
I tried to create the task Specific class so that I can delegate the work to them.
But I think my entrypoint class is still doing a lot of things. According to good design "a class should only be doing one thing".
There are other tasks that I have ommitted intentionally for brevity.
Not sure if my question is clear but I just wanted to improve my code.
I have used java code in this case but I think this is still applicable to other languages.
How to refactor?

Related

How to write Xunit test case of factory design pattern code block which is tightly coupled?

I would like to write xunit test case of below method. Could you please suggest alternate design so i can write xunit test case with minimum change in my current project.
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = ContextFactory.Current.GetDomain<EmployeeDomain>().GetEmployeeFilterAsync(id,
CurrentUser.CompanyId, filter); // Not able write unit test case , please suggest alternate design.
return View("View", response);
}
}
current design is as follow
public interface IDomain
{
}
public interface IContext
{
D GetDomain<D>() where D : IDomain;
string ConnectionString { get; }
}
public class ApplicationContext : IContext
{
public D GetDomain<D>() where D : IDomain
{
return (D)Activator.CreateInstance(typeof(D));
}
public string ConnectionString
{
get
{
return "DatabaseConnection";
}
}
}
public class ContextFactory
{
private static IContext _context;
public static IContext Current
{
get
{
return _context;
}
}
public static void Register(IContext context)
{
_context = context;
}
}
//var response = ContextFactory.Current.GetDomain**< EmployeeDomain>**().GetEmployeeFilterAsync(id,
CompanyId, filter);
This line serve purpose to call specific class method i.e GetEmployeeFilterAsync from EmployeeDomain. Although it is very handy and widely used in our application but due to design issue i am not able to write unit
test case.
Could you please suggest design so with the minimum change we can write unit test case.
Don't use the Service Locator anti-pattern, use Constructor Injection instead. I can't tell what AssetDomain is from the OP, but it seems as though it's the dependency that matters. Inject it into the class:
public class ProbablySomeController
{
public ProbablySomeController(AssetDomain assetDomain)
{
AssetDomain = assetDomain;
}
public AssetDomain AssetDomain { get; }
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = AssetDomain.GetAssetFilterAsync(id, CurrentUser.CompanyId, filter);
return View("View", response);
}
}
}
Assuming that AssetDomain is a polymorphic type, you can now write a test and inject a Test Double:
[Fact]
public void MyTest()
{
var testDouble = new AssetDomainTestDouble();
var sut = new ProbablySomeController(testDouble);
var actual = sut.Index(42, AssetFilterType.All);
// Put assertions here
}
step1 : Required library
step 2 : When the application starts , register required domain like
protected void Application_Start()
UnityConfig.RegisterComponents();
Step 3: create one static class and register all your domain
example
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
Initialize domain which will injected in controller
container.RegisterType<IPricingDomain, PricingDomain>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
step 4 :
so you can inject respective interface in constructor
in controller file.
goal : get rid of below any pattern in your project.
and start writing unit test cases.

Reading application.properties from any class in spring boot

When I add a property in the application.properties files, this can be access from the main class without any problem.
#SpringBootApplication
#ComponentScan(basePackages = "com.example.*")
public class MailTestApplication implements CommandLineRunner {
#Value("${admin.mail}")
String email;
public static void main(String[] args) {
SpringApplication.run(MailTestApplication.class, args);
}
#Override
public void run(String... strings) throws Exception {
System.out.println(email);
Email email = new Email();
email.sendMail();
}
}
However, when I try to access it from any other class it is never retrieved.
#Component
public class Email {
#Autowired
private MailSender sender;
#Value("${admin.mail}")
String email;
public Email() {
}
public void sendMail() {
SimpleMailMessage msg = new SimpleMailMessage();
System.out.println(email);
msg.setTo("sample#email.com");
msg.setSubject("Send mail by Spring Boot");
msg.setText("Send mail by Spring Boot");
sender.send(msg);
}
}
I was reading some of the previous questions other users posted without a clear result for me. I even tried to find some examples with similar resutl.
Could someone give me any clue about this?
Thanks a lot in advance.
The #Value should work (Im asuming your class is under the com.example.* package since you are scanning that package) but if you want to do it another way this is what im using :
public class JpaConfiguration {
public static final String TRANSACTION_MANAGER_NAME = "jpaTransactionManager";
#Autowired
Environment applicationProperties;
Then to use it
#Bean
public DriverManagerDataSource driverManagerDataSource() {
DriverManagerDataSource driverConfig = new DriverManagerDataSource();
driverConfig.setDriverClassName(applicationProperties.getProperty("data.jpa.driverClass"));
driverConfig.setUrl(applicationProperties
.getProperty("data.jpa.connection.url"));
driverConfig.setUsername(applicationProperties
.getProperty("data.jpa.username"));
driverConfig.setPassword(applicationProperties
.getProperty("data.jpa.password"));
return driverConfig;
}
UPDATE AFTER GETTING THE GITHUB REPO
I Don't really know what you are trying to build but :
If you do this:
#Override
public void run(String... strings) throws Exception {
//System.out.println(email);
Email email = new Email();
email.sendMail();
}
Then you are creating the instance of the class, and not spring. so you shouldn't be creating the instance yourself there it should be spring.
That said, i dont know if you are creating a web application a command line application or both.
That said ill give you a minor solution to show you that the dependency injection is in fact working.
1_ add a getter to your email on email class. remove the CommandLine interface (If you want to implement this i would recomend you to put CommandLine implmentations on another package say Controller);
And then run your app like this:
#SpringBootApplication
#ComponentScan(basePackages = "com.example")
public class MailTestApplication {
#Value("${admin.mail}")
String email;
public static void main(String[] args) {
// SpringApplication.run(MailTestApplication.class, args);
final ConfigurableApplicationContext context = new SpringApplicationBuilder(MailTestApplication.class).run(args);
Email e = context.getBean(Email.class);
System.out.println(e.getEmail());
}
The Key thing I want to show is that the instance is created by spring thats why the wiring works. and the email gets printed in the console.
Regarding the email class :
#Component
public class Email {
// #Autowired
// private MailSender sender;
#Value("${admin.mail}")
String email;
public Email() {
}
public void sendMail() {
SimpleMailMessage msg = new SimpleMailMessage();
System.out.println(email);
msg.setTo("sample#email.com");
msg.setSubject("Send mail by Spring Boot");
msg.setText("Send mail by Spring Boot");
// sender.send(msg);
}
public String getEmail() {
return email;
}
}
I Comment out the MailSender since I think you need to configure that too, i have made a custom mailSender that uses gmail and other for mailChimp that i can share with you if you need. but again I dont really know what your intent with the app is.
Hope the info helps you.

In OOP reading from text file should be a Independent class method?

I have a class that only have main which read in some txt and do the algorithms.
my class is look like:
class doThejob{
public static void main(String args[]){
//*****start part A******
//do the reading from text file, and tokenize it
// process into the form I need,
//about 10-30 lines of codes
//******End of part A*****
//then run the algorithms
algorithm alg=new aglorithm();
Object output = alg.x(input);
//****Part B**** output to txt, about 10~40 lines
}
}
class algorithm{
private void a(Object x){
//do something
return (Object)result;
}
}
Can anyone tell me should I extract those part A and part B to a new class ,and then setup them as a public method .like below
class Io{
public Object readFromTxt(String path){
}
public void outputToTxt(String path){
}
}
And if I setup them , and then use it like below, is that more OOP?
class doThejob{
public static void main(String args[]){
Io dataProcess= new Io();
Object input = dataProcess.readFromTxt(args[0]);
algorithm alg=new aglorithm();
Object output =alg.x(input);
dataProcess.readFromTxt(args[1],output);
}
}
class algorithm{
private Object a(Object x){
//do something
}
}
Do it the way you fill is more readable.
Separating this in another class is according to the Single Responsability Principle. It will help making the code more readable and easy to change later on.
If you want to expand more on this, you could create an interface (eg.: IIO) for input and output. This way you can implement this interface in the IO class, renaming it to FileIO. Anytime you want to create another form of IO, like database access, you just have to create a DatabaseIO class that implements this interface and change the instance in the main method for this new type:
public interface IIO
{
string Read();
void Write(string text);
}
public class FileIO : IIO
{
string path;
public FileIO(string filePath)
{
path = filePath;
}
public string Read()
{
// read from file and return contents
}
public void Write(string text)
{
// write to file
}
}
public class SqlServerIO : IIO
{
SqlConnection conn;
public SqlServerIO(string connectionStringName)
{
// create the connection
}
public string Read()
{
// read from database
}
public void Write(string text)
{
// write to database
}
}
Extracting interfaces makes the code more maintenable by alowing to switch implementations anytime without messing with working code. It also facilitates unit testing.

How to do Setup of mocks with Ninject's MockingKernel (moq)

I'm having a really hard time trying to figure how I can do .SetupXXX() calls on the underlying Mock<T> that has been generated inside the MockingKernel. Anyone who can shed some light on how it is supposed to work?
You need to call the GetMock<T> method on the MoqMockingKernel which will return the generated Mock<T> on which you can call your .SetupXXX()/VerifyXXX() methods.
Here is an example unit test which demonstrates the GetMock<T> usage:
[Test]
public void Test()
{
var mockingKernel = new MoqMockingKernel();
var serviceMock = mockingKernel.GetMock<IService>();
serviceMock.Setup(m => m.GetGreetings()).Returns("World");
var sut = mockingKernel.Get<MyClass>();
Assert.AreEqual("Hello World", sut.SayHello());
}
Where the involved types are the following:
public interface IService { string GetGreetings(); }
public class MyClass
{
private readonly IService service;
public MyClass(IService service) { this.service = service; }
public string SayHello()
{
return string.Format("Hello {0}", service.GetGreetings());
}
}
Note that you can access the generated Moq.MockRepository (if you prefer it over the SetupXXX methods) with the MoqMockingKernel.MockRepository property.

Google Guice, Interceptors and PrivateModules

New poster here, hope I don't brake any rules :)
I am using PrivateModule in google-guice in order to have multiple DataSource's for the same environment. But I am having a hard time getting MethodInterceptor's to work inside the private modules.
Below is a simple test case that explains the "problem".
A simple service class would be:
interface Service {
String go();
}
class ServiceImpl implements Service {
#Override #Transactional
public String go() {
return "Test Case...";
}
}
The MyModule class would be:
class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new PrivateModule() {
#Override
protected void configure() {
bind(Service.class).to(ServiceImpl.class);
bindInterceptor(
Matchers.any(),
Matchers.annotatedWith(Transactional.class),
new MethodInterceptor() {
#Override
public Object invoke(MethodInvocation i)
throws Throwable {
System.out.println("Intercepting: "
+ i.getMethod().getName());
return i.proceed();
}
});
expose(Service.class);
}
});
}
}
And the final test case:
public class TestCase {
#Inject Service service;
public TestCase() {
Guice.createInjector(new MyModule()).injectMembers(this);
}
public String go() {
return service.go();
}
public static void main(String[] args) {
TestCase t = new TestCase();
System.out.println(t.go());
}
}
You would expect the output to be:
Intercepting: go
Test Case...
But it doesn't happen, the interceptor is not used, ant only Test Case... is output.
If I bind/expose the ServiceImpl instead of the interface then it works.
Thanks in advance,
Regards,
LL
Well... I figured it out shortly after I posted the question :)
The problem is that you also need to expose() the ServiceImpl class.
So the bind/expose would be.
bind(ServiceImpl.class); // ServiceImpl annotated with #Singleton
bind(Service.class).to(ServiceImpl.class);
expose(ServiceImpl.class);
expose(Service.class);
Regards,
LL
You need to explicitly bind ServiceImpl in the private module. The problem with your existing code is that it inherits the binding for ServiceImpl from the parent module. From the PrivateModule docs,
Private modules are implemented using parent injectors. When it can satisfy their dependencies, just-in-time bindings will be created in the root environment. Such bindings are shared among all environments in the tree.
Adding this line should fix the problem:
bind(ServiceImpl.class);