-
Notifications
You must be signed in to change notification settings - Fork 23
Description
A constructor should be as free of side effects as possible. If I/O has to be done before other operations, I would make this initialization explicit with, for example, a void init() method. I would make the constructor protected and provide a static factory method that also does the initialization and I/O, throwing an IOException or HaskellIOException. A HaskellIOException which subclasses IOException instead of just wrapping the IOException in a HaskellException would make methods that perform I/O more obvious, and I/O exceptions could be handled in the outside context intelligently, whether HaskellIOException or other.
Forking processes is an even heavier operation than I/O, and it should always be transparent to the calling context that it is happening. You can accidentally create zombies and other hazards on the host machine when you fork new system processes. Definitely not something to do in a constructor.
I just cloned viskell and first did mvn package and the tests requiring haskell executables failed at the constructor to Evaluator.
Test set: nl.utwente.viskell.ghcj.GhciEvaluatorTest
-------------------------------------------------------------------------------
Tests run: 3, Failures: 0, Errors: 3, Skipped: 0, Time elapsed: 0.016 sec <<< FAILURE!
typeErrorTest(nl.utwente.viskell.ghcj.GhciEvaluatorTest) Time elapsed: 0.01 sec <<< ERROR!
nl.utwente.viskell.ghcj.HaskellException: java.io.IOException: Cannot run program "stack": error=2, No such file or directory
at nl.utwente.viskell.ghcj.Evaluator.<init>(Evaluator.java:60)
at nl.utwente.viskell.ghcj.GhciEvaluator.<init>(GhciEvaluator.java:13)
at nl.utwente.viskell.ghcj.GhciEvaluatorTest.startGhci(GhciEvaluatorTest.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.io.IOException: Cannot run program "stack": error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at nl.utwente.viskell.ghcj.Evaluator.<init>(Evaluator.java:55)
... 31 more
Caused by: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
at java.lang.ProcessImpl.start(ProcessImpl.java:134)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 32 more